This project was completed for the MUSA/Smart Cities Practicum course
(MUSA 801) instructed by Michael Fichman and Matthew Harris. We are
grateful to our instructors for their continued support and feedback. We
would like to give special thanks to KC Filippino and Ben McFarlane from
Hampton Roads Planning District Commission, and Dexter Locke from the
United States Forest Service for providing data, insight, and support
throughout the semester. This project would not have been possible
without them.
8. Code Appendix
########### Required Packages ###########
packages = c("stars","starsExtra", "abind","tigris","tidycensus","dyplyr",
"bayesplot", "lme4","RcppEigen","knitr","yardstick",
"tidyverse", "tidyr", "broom", "caret", "dials", "doParallel", "e1071", "earth",
"ggrepel", "glmnet", "ipred", "klaR", "kknn", "pROC", "rpart", "randomForest",
"sessioninfo", "tidymodels","ranger", "recipes", "workflows", "themis","xgboost",
"sf", "nngeo", "mapview","raster")
########### Define Functions ###########
Load.fun <- function(x) {
x <- as.character(x)
if(isTRUE(x %in% .packages(all.available=TRUE))) {
eval(parse(text=paste("require(", x, ")", sep="")))
print(paste(c(x, " : already installed; requiring"), collapse=''))
} else {
#update.packages()
print(paste(c(x, " : not installed; installing"), collapse=''))
eval(parse(text=paste("install.packages('", x, "')", sep="")))
print(paste(c(x, " : installed and requiring"), collapse=''))
eval(parse(text=paste("require(", x, ")", sep="")))
}
}
for(i in seq_along(packages)){
packge <- as.character(packages[i])
Load.fun(packge)
}
plotTheme <- function(base_size = 12, title_size = 12) {
theme(
text = element_text( color = "black"),
plot.title = element_text(size = title_size, colour = "black"),
plot.subtitle = element_text(face="italic"),
plot.caption = element_text(hjust=0),
axis.ticks = element_blank(),
panel.background = element_blank(),
panel.grid.minor = element_line("grey90", size = 0.01),
panel.grid.major = element_line("grey90", size = 0.01),
panel.border = element_rect(colour = "white" , fill=NA, size=0),
strip.background = element_rect(color = "white",fill='white'),
strip.text = element_text(size=12),
axis.title = element_text(size=12),
axis.text = element_text(size=10),
plot.background = element_blank(),
legend.background = element_blank(),
legend.title = element_text(colour = "black", face = "italic"),
legend.text = element_text(colour = "black", face = "italic"),
strip.text.x = element_text(size = 8)
)
}
mapTheme <- theme(plot.title =element_text(size=12),
plot.subtitle = element_text(size=8),
plot.caption = element_text(size = 6),
axis.line=element_blank(),
axis.text.x=element_blank(),
axis.text.y=element_blank(),
axis.ticks=element_blank(),
axis.title.x=element_blank(),
axis.title.y=element_blank(),
panel.background=element_blank(),
panel.border=element_blank(),
panel.grid.major=element_line(colour = 'transparent'),
panel.grid.minor=element_blank(),
legend.direction = "vertical",
legend.position = "right",
plot.margin = margin(1, 1, 1, 1, 'cm'),
legend.key.height = unit(1, "cm"), legend.key.width = unit(0.2, "cm"))
palette2 <- c("#41b6c4","#253494")
palette4 <- c("#a1dab4","#41b6c4","#2c7fb8","#253494")
palette5 <- c("#ffffcc","#a1dab4","#41b6c4","#2c7fb8","#253494")
palette10 <- c("#f7fcf0","#e0f3db","#ccebc5","#a8ddb5","#7bccc4",
"#4eb3d3","#2b8cbe","#0868ac","#084081","#f7fcf0")
#########################################################################################################################################
################################################### -------------------- ##############################################################
################################################### | | ##############################################################
################################################### | DATA PREPARATION | ##############################################################
################################################### | | ##############################################################
################################################### -------------------- ##############################################################
#########################################################################################################################################
# load all the land cover data
port_14 <- read_stars("~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/lc/port_51740_lc_2014/port_51740_landcover_2014.tif")
port_18 <- read_stars("~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/lc/port_51740_lc_2018/port_51740_landcover_2018.tif")
james_14 <- read_stars("~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/lc/jame_51095_lc_2014/jame_51095_landcover_2014.tif")
james_18 <- read_stars("~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/lc/jame_51095_lc_2018/jame_51095_landcover_2018.tif")
isle_14_10 <- read_stars("~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/lc/islelc_14_10x10.tif")
isle_18_10 <- read_stars("~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/lc/islelc_18_10x10.tif")
# load all the boundary data
port_area <- st_read("~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/boundary/portsmouth.shp")
james_area <- st_read("~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/boundary/James.shp")
isle_area <- st_read("~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/boundary/Isle_of_Wight.shp")
#############################################################################################################################
############################################# -------------------- ########################################################
############################################# | LANDCOVER DATASET | ########################################################
############################################# -------------------- ########################################################
#############################################################################################################################
# Resample the raster image to 10x10 cells
port_14_10 <- st_warp(port_14, cellsize = 10, crs = st_crs(port_14))
port_18_10 <- st_warp(port_18, cellsize = 10, crs = st_crs(port_18))
jame_14_10 <- st_warp(jame_14, cellsize = 10, crs = st_crs(jame_14))
jame_18_10 <- st_warp(jame_18, cellsize = 10, crs = st_crs(jame_18))
port_area <- port_area %>%
st_transform(crs = st_crs(port_14))
jame_area <- jame_area %>%
st_transform(crs = st_crs(jame_14))
isle_area <- isle_area %>%
st_transform(crs = st_crs(isle_14))
# Crop the resampled raster image to the test area
port_14_10_crop <- st_crop(port_14_10, port_area)
port_18_10_crop <- st_crop(port_18_10, port_area)
jame_14_10_crop <- st_crop(jame_14_10, jame_area)
jame_18_10_crop <- st_crop(jame_18_10, jame_area)
isle_14_10_crop <- st_crop(isle_14, isle_area)
isle_18_10_crop <- st_crop(isle_18, isle_area)
# Create land cover change feature
port_change <- c(port_18_10_crop - port_14_10_crop)%>%
mutate(lcchange = case_when(port_51740_landcover_2018.tif != 0 ~ 1,
port_51740_landcover_2018.tif != 0 ~ 0))
jame_change <- c(jame_18_10_crop - jame_14_10_crop)%>%
mutate(lcchange = case_when(jame_51095_landcover_2018.tif != 0 ~ 1,
jame_51095_landcover_2014.tif!= 0 ~ 0))
isle_change <- c(isle_18_10_crop - isle_14_10_crop)%>%
mutate(lcchange = case_when(islelc_18_10x10.tif != 0 ~ 1,
islelc_18_10x10.tif != 0 ~ 0))
# Reclassify the cropped raster image
port_14_10_rc <- port_14_10_crop %>%
mutate(
originallc = port_51740_landcover_2014.tif,
lc = case_when(
port_51740_landcover_2014.tif < 6 ~ 0, # previous
port_51740_landcover_2014.tif >= 6 ~ 1 # impervious
))
port_18_10_rc <- port_18_10_crop %>%
mutate(
originallc = port_51740_landcover_2018.tif,
lc = case_when(
port_51740_landcover_2018.tif < 6 ~ 0,
port_51740_landcover_2018.tif >= 6 ~ 1
))
jame_14_10_rc <- jame_14_10_crop %>%
mutate(originallc = jame_51095_landcover_2014.tif,
lc = case_when(
jame_51095_landcover_2014.tif < 6 ~ 0, # permeable
jame_51095_landcover_2014.tif >= 6 ~ 1 # impermeable
))
jame_18_10_rc <- jame_18_10_crop %>%
mutate(originallc = jame_51095_landcover_2018.tif,
lc = case_when(
jame_51095_landcover_2018.tif < 6 ~ 0,
jame_51095_landcover_2018.tif >= 6 ~ 1
))
isle_14_10_rc <- isle_14_10_crop %>%
mutate(originallc = case_when(
islelc_14_10x10.tif == 1 ~ 1,
islelc_14_10x10.tif == 2 ~ 2,
islelc_14_10x10.tif == 3 ~ 3,
islelc_14_10x10.tif == 4 ~ 4,
islelc_14_10x10.tif == 5 ~ 5,
islelc_14_10x10.tif == 6 ~ 6,
islelc_14_10x10.tif == 7 ~ 7,
islelc_14_10x10.tif == 8 ~ 8,
islelc_14_10x10.tif == 9 ~ 9,
islelc_14_10x10.tif == 10 ~ 10,
islelc_14_10x10.tif == 11 ~ 11,
islelc_14_10x10.tif == 12 ~ 12
),
lc = case_when(
islelc_14_10x10.tif < 6 ~ 0, # permeable
islelc_14_10x10.tif >= 6 ~ 1 # impermeable
))
isle_18_10_rc <- isle_18_10_crop %>%
mutate(
originallc =case_when(
islelc_18_10x10.tif == 1 ~ 1,
islelc_18_10x10.tif == 2 ~ 2,
islelc_18_10x10.tif == 3 ~ 3,
islelc_18_10x10.tif == 4 ~ 4,
islelc_18_10x10.tif == 5 ~ 5,
islelc_18_10x10.tif == 6 ~ 6,
islelc_18_10x10.tif == 7 ~ 7,
islelc_18_10x10.tif == 8 ~ 8,
islelc_18_10x10.tif == 9 ~ 9,
islelc_18_10x10.tif == 10 ~ 10,
islelc_18_10x10.tif == 11 ~ 11,
islelc_18_10x10.tif == 12 ~ 12
),
lc = case_when(
islelc_18_10x10.tif < 6 ~ 0,
islelc_18_10x10.tif >= 6 ~ 1
))
# Create reclassed land cover change feature
port_change_rc <- (port_18_10_rc - port_14_10_rc)
jame_change_rc <- (jame_18_10_rc - jame_14_10_rc)
isle_change_rc <- (isle_18_10_rc - isle_14_10_rc)
#remove
rm(port_14_10,port_18_10,port_14,port_18)
rm(jame_14_10,jame_18_10,jame_14,jame_18)
rm(isle_14_10,isle_18_10,isle_14,isle_18)
#############################################################################################################################
############################################# -------------------- ########################################################
############################################# | CENSCUS DATASET | ########################################################
############################################# -------------------- ########################################################
#############################################################################################################################
## load census
options(tigris_use_cache = TRUE)
census_api_key("bd4ce20561125a8480632db6acb29869e040ed08",install = TRUE)
# Define function to retrieve census data for a given county and year
get_county_data <- function(state, county, year) {
get_acs(
geography = "block group",
variables = c("B01003_001E","B02001_002E","B19013_001E","B25002_001E","B06012_002E","B27011_008E"),
year = year,
state = state,
county = county,
geometry = TRUE,
output = "wide"
) %>%
st_transform(st_crs(port_18)) %>%
rename(
TotalPop = B01003_001E,
Whites = B02001_002E,
MedHHInc = B19013_001E,
TotalUnit = B25002_001E
) %>%
mutate(
pctWhite = ifelse(TotalPop > 0, Whites / TotalPop * 100, 0),
area = st_area(geometry)
) %>%
dplyr::select(-NAME, -starts_with("B"),-Whites)%>%
fill(everything())
}
# Define function to calculate changes in census variables between two years
calculate_changes <- function(data1, data2) {
data2 %>%
st_join(data1,left = TRUE) %>%
mutate(
popchange = (TotalPop.y - TotalPop.x) / (TotalPop.x * area.x),
pctwhitechange = (pctWhite.y - pctWhite.x),
Unitchange = (TotalUnit.y - TotalUnit.x) / area.x,
MedHHIncchange = (MedHHInc.y - MedHHInc.x) / area.x,
Area = area.x,
GEOID = GEOID.x
)%>%
dplyr::select(-ends_with(".x"),-ends_with(".y"))
}
# Retrieve census data for Portsmouth in 2014 and
portsmouth_14 <- get_county_data(state = "51", county = "Portsmouth", year = 2014)
portsmouth_18 <- get_county_data(state = "51", county = "Portsmouth", year = 2018)
portsmouth_21 <- get_county_data(state = "51", county = "Portsmouth", year = 2021)
# Calculate changes in census variables between 2014 and 2018
port_tract <- calculate_changes(data1 = portsmouth_14, data2 = portsmouth_18)
port_tract2 <- calculate_changes(data1 = portsmouth_18, data2 = portsmouth_21)
# Repeat for James City and Isle of Wight counties
james_city_14 <- get_county_data(state = "51", county = "James City", year = 2014)
james_city_18 <- get_county_data(state = "51", county = "James City", year = 2018)
james_city_21 <- get_county_data(state = "51", county = "James City", year = 2021)
jame_tract <- calculate_changes(data1 = james_city_14, data2 = james_city_18)
jame_tract2 <- calculate_changes(data1 = james_city_18, data2 = james_city_21)
isle_of_wight_14 <- get_county_data(state = "51", county = "Isle of Wight", year = 2014)
isle_of_wight_18 <- get_county_data(state = "51", county = "Isle of Wight", year = 2018)
isle_of_wight_21 <- get_county_data(state = "51", county = "Isle of Wight", year = 2021)
isle_tract <- calculate_changes(data1 = isle_of_wight_14, data2 = isle_of_wight_18)
isle_tract2 <- calculate_changes(data1 = isle_of_wight_18, data2 = isle_of_wight_21)
#############################################################################################################################
############################################# -------------------- ########################################################
############################################# | DEM DATASET | ########################################################
############################################# -------------------- ########################################################
#############################################################################################################################
dem1 <- read_stars("~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/DEM/USGS_1_n38w077_20170509.tif")
dem2 <- read_stars("~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/DEM/USGS_1_n37w077_20160315.tif")
dem <- st_mosaic(dem1, dem2)
dem2 <- st_warp(dem2, crs=st_crs(port_14))
dem_port <- st_crop (dem2, port_area)
dem_port <- st_warp(dem_port, port_14)
port_slope<- slope(dem_port)
dem1 <- st_warp(dem1, crs=st_crs(jame_area))
dem_james <- st_crop (dem1, jame_area)
dem_james <- st_warp(dem_james, jame_18_10_crop)
james_slope<- slope(dem_james)
dem2 <- st_warp(dem, crs=st_crs(isle_14_10_rc))
dem_isle <- st_crop (dem2, isle_area)
dem_isle <- st_warp(dem_isle, isle_14_10_crop)
isle_slope<- slope(dem_isle)
rm(dem1,dem2,dem)
#############################################################################################################################
############################################# -------------------- ########################################################
############################################# | SOIL DATASET | ########################################################
############################################# -------------------- ########################################################
#############################################################################################################################
# Portmouth
soil <- st_read('~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/Soil/Port/port_soil.shp', crs= 'EPSG:4326')
soilclass <- soil%>%
mutate(soil = case_when(
Port__Rati == 'D' ~ 6,
Port__Rati == 'C' ~ 5,
Port__Rati == 'B/D' ~ 4,
Port__Rati == 'B' ~ 3,
Port__Rati == 'A/D' ~ 2,
Port__Rati == 'A' ~ 1,
is.na(Port__Rati) ~ 0
)) %>%
dplyr::select(-colnames(soil),geometry)%>%
st_transform(st_crs(port_14_10_rc))
soil_port <- st_crop(soilclass, port_area)
# James City
soil <- st_read('~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/Soil/James/James_soil.shp', crs= 'EPSG:4326')
soilclass <- soil%>%
mutate(soil = case_when(
Report___8 == 'D' ~ 6,
Report___8 == 'C' ~ 5,
Report___8 == 'B/D' ~ 4,
Report___8 == 'B' ~ 3,
Report___8 == 'A/D' ~ 2,
Report___8 == 'A' ~ 1,
is.na(Report___8) ~ 0
)) %>%
dplyr::select(-colnames(soil),geometry)%>%
st_transform(st_crs(jame_14_10_rc))
soil_jame <- st_crop(soilclass, jame_area)
# Isle of Wight
soil <- st_read('~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/Soil/isle/isle_soil.shp', crs= 'EPSG:4326')
soilclass <- soil%>%
mutate(soil = case_when(
isle__Ra_1 == 'D' ~ 6,
isle__Ra_1 == 'C' ~ 5,
isle__Ra_1 == 'B/D' ~ 4,
isle__Ra_1 == 'B' ~ 3,
isle__Ra_1 == 'A/D' ~ 2,
isle__Ra_1 == 'A' ~ 1,
is.na(isle__Ra_1) ~ 0
)) %>%
dplyr::select(-colnames(soil),geometry)%>%
st_transform(st_crs(isle_14_10_rc))
soil_isle <- st_crop(soilclass, isle_area)
#############################################################################################################################
############################################# -------------------- ########################################################
############################################# | SPATIAL CALCULATION | #######################################################
############################################# -------------------- ########################################################
#############################################################################################################################
port_14_pcnt_imperv = focal2(port_14_10_rc["lc"], matrix(1, 3, 3), "mean")
port_18_pcnt_imperv = focal2(port_18_10_rc["lc"], matrix(1, 3, 3), "mean")
jame_14_pcnt_imperv = focal2(jame_14_10_rc["lc"], matrix(1, 3, 3), "mean")
jame_18_pcnt_imperv = focal2(jame_18_10_rc["lc"], matrix(1, 3, 3), "mean")
isle_14_pcnt_imperv = focal2(isle_14_10_rc["lc"], matrix(1, 3, 3), "mean")
isle_18_pcnt_imperv = focal2(isle_18_10_rc["lc"], matrix(1, 3, 3), "mean")
# Function to calculate focal mean
calc_focal_mean <- function(df, field, ksize) {
focal2(df[field], matrix(1, ksize, ksize), "mean") %>%
focal2(., matrix(1, ksize, ksize), "mean") %>%
focal2(., matrix(1, ksize, ksize), "mean")
}
#############################################################################################################################
############################################# -------------------- ########################################################
############################################# | PORTMOUTH | #######################################################
############################################# -------------------- ########################################################
#############################################################################################################################
# Road
port_14_road <- port_14_10_crop %>%
mutate(road = as.numeric(port_51740_landcover_2014.tif == 9))
port_18_road <- port_18_10_crop %>%
mutate(road = as.numeric(port_51740_landcover_2018.tif == 9))
road_14 <- calc_focal_mean(port_14_road, "road", 3)
road_18 <- calc_focal_mean(port_18_road, "road", 3)
# Canopy
port_14_canopy <- port_14_10_crop %>%
mutate(canopy = as.numeric(port_51740_landcover_2014.tif == 3))
port_18_canopy <- port_18_10_crop %>%
mutate(canopy = as.numeric(port_51740_landcover_2018.tif == 3))
canopy_14_mean <- calc_focal_mean(port_14_canopy, "canopy", 3)
canopy_18_mean <- calc_focal_mean(port_18_canopy, "canopy", 3)
# Shrub
port_14_shrub <- port_14_10_crop %>%
mutate(shrub = as.numeric(port_51740_landcover_2014.tif == 2))
port_18_shrub <- port_18_10_crop %>%
mutate(shrub = as.numeric(port_51740_landcover_2018.tif == 2))
shrub_14_mean <- calc_focal_mean(port_14_shrub, "shrub", 3)
shrub_18_mean <- calc_focal_mean(port_18_shrub, "shrub", 3)
# Water
port_14_water <- port_14_10_crop %>%
mutate(water = as.numeric(port_51740_landcover_2014.tif == 1))
port_18_water <- port_18_10_crop %>%
mutate(water = as.numeric(port_51740_landcover_2018.tif == 1))
water_14_mean <- calc_focal_mean(port_14_water, "water", 25)
water_18_mean <- calc_focal_mean(port_18_water, "water", 25)
# Other
port_14_other <- port_14_10_crop %>%
mutate(other = as.numeric(port_51740_landcover_2014.tif == 8))
port_18_other <- port_18_10_crop %>%
mutate(other = as.numeric(port_51740_landcover_2018.tif == 8))
other_14_mean <- focal2(port_14_other["other"], matrix(1, 3, 3), "mean")
other_14_mean <- focal2(other_14_mean["other"], matrix(1, 3, 3), "mean")
other_18_mean <- focal2(port_18_other["other"], matrix(1, 3, 3), "mean")
other_18_mean<- focal2(other_18_mean["other"], matrix(1, 3, 3), "mean")
## join all the data
port14 <- cbind(
as.data.frame(canopy_14_mean)['canopy'],
as.data.frame(road_14)['road'],
as.data.frame(other_14_mean)['other'],
as.data.frame(shrub_14_mean)['shrub'],
as.data.frame(water_14_mean)['water'],
as.data.frame(port_14_pcnt_imperv)['lc'] %>%
rename(imperv = lc ),
as.data.frame(port_change_rc)[4]%>%
rename(lcchange = lc )
)
port18 <- cbind(
as.data.frame(canopy_18_mean)['canopy'],
as.data.frame(road_18)['road'],
as.data.frame(other_18_mean)['other'],
as.data.frame(shrub_18_mean)['shrub'],
as.data.frame(water_18_mean)['water'],
as.data.frame(port_18_pcnt_imperv)['lc'] %>%
rename(imperv = lc )
)
port_14 <-
st_join(port_14_10_rc,port_tract) %>%
st_join(.,dem_port)%>% # not changing
st_join(.,port_slope) %>%
st_join(., soil_port)
port_18 <-
st_join(port_18_10_rc,port_tract2) %>%
st_join(.,dem_port)%>% # not changing
st_join(.,port_slope) %>%
st_join(., soil_port)
rm(dem_port,port_slope, port_14_10_crop, port_14_10_rc, port_14_canopy, port_14_other, port_14_road, port_14_water, port_18_10_crop, port_18_10_rc, port_18_canopy, port_18_other, port_18_road, port_18_water)
port14_df <-
as.data.frame(port_14) %>%
rename(
terrain = USGS_1_n37w077_20160315.tif )%>%
cbind(., port14)%>% na.omit()
port18_df <-
as.data.frame(port_18) %>%
rename(
terrain = USGS_1_n37w077_20160315.tif) %>%
cbind(., port18)%>%na.omit()
saveRDS(port14_df, "~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/output/port14_df.rds")
saveRDS(port18_df, "~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/output/port18_df.rds")
#############################################################################################################################
############################################# -------------------- ########################################################
############################################# | JAME CITY | ########################################################
############################################# -------------------- ########################################################
#############################################################################################################################
# Road
jame_14_road <- jame_14_10_crop %>%
mutate(road = as.numeric(jame_51095_landcover_2014.tif == 9))
jame_18_road <- jame_18_10_crop %>%
mutate(road = as.numeric(jame_51095_landcover_2018.tif == 9))
road_14 <- calc_focal_mean(jame_14_road, "road", 3)
road_18 <- calc_focal_mean(jame_18_road, "road", 3)
# Canopy
jame_14_canopy <- jame_14_10_crop %>%
mutate(canopy = as.numeric(jame_51095_landcover_2014.tif == 3))
jame_18_canopy <- jame_18_10_crop %>%
mutate(canopy = as.numeric(jame_51095_landcover_2018.tif == 3))
canopy_14_mean <- calc_focal_mean(jame_14_canopy, "canopy", 3)
canopy_18_mean <- calc_focal_mean(jame_18_canopy, "canopy", 3)
# Shrub
jame_14_shrub <- jame_14_10_crop %>%
mutate(shrub = as.numeric(jame_51095_landcover_2014.tif == 2))
jame_18_shrub <- jame_18_10_crop %>%
mutate(shrub = as.numeric(jame_51095_landcover_2018.tif == 2))
shrub_14_mean <- calc_focal_mean(jame_14_shrub, "shrub", 3)
shrub_18_mean <- calc_focal_mean(jame_18_shrub, "shrub", 3)
# Water
jame_14_water <- jame_14_10_crop %>%
mutate(water = as.numeric(jame_51095_landcover_2014.tif == 1))
jame_18_water <- jame_18_10_crop %>%
mutate(water = as.numeric(jame_51095_landcover_2018.tif == 1))
water_14_mean <- calc_focal_mean(jame_14_water, "water", 25)
water_18_mean <- calc_focal_mean(jame_18_water, "water", 25)
# Other
jame_14_other <- jame_14_10_crop %>%
mutate(other = as.numeric(jame_51095_landcover_2014.tif == 8))
jame_18_other <- jame_18_10_crop %>%
mutate(other = as.numeric(jame_51095_landcover_2018.tif == 8))
other_14_mean <- focal2(jame_14_other["other"], matrix(1, 3, 3), "mean")
other_14_mean <- focal2(other_14_mean["other"], matrix(1, 3, 3), "mean")
other_18_mean <- focal2(jame_18_other["other"], matrix(1, 3, 3), "mean")
other_18_mean<- focal2(other_18_mean["other"], matrix(1, 3, 3), "mean")
## join all the data
jame14 <- cbind(
as.data.frame(canopy_14_mean)['canopy'],
as.data.frame(road_14)['road'],
as.data.frame(other_14_mean)['other'],
as.data.frame(shrub_14_mean)['shrub'],
as.data.frame(water_14_mean)['water'],
as.data.frame(jame_14_pcnt_imperv)['lc'] %>%
rename(imperv = lc ),
as.data.frame(jame_change_rc)['lc']%>%
rename(lcchange = lc )
)
jame18 <- cbind(
as.data.frame(canopy_18_mean)['canopy'],
as.data.frame(road_18)['road'],
as.data.frame(other_18_mean)['other'],
as.data.frame(shrub_18_mean)['shrub'],
as.data.frame(water_18_mean)['water'],
as.data.frame(jame_18_pcnt_imperv)['lc'] %>%
rename(imperv = lc )
)
jame_14 <-
st_join(jame_14_10_rc,jame_tract) %>%
st_join(.,dem_james)%>% # not changing
st_join(.,james_slope) %>%
st_join(., soil_jame)
jame_18 <-
st_join(jame_18_10_rc,jame_tract2) %>%
st_join(.,dem_james)%>% # not changing
st_join(.,james_slope) %>%
st_join(., soil_jame)
rm(dem_jame,jame_slope, jame_14_10_crop, jame_14_10_rc, jame_14_canopy, jame_14_other, jame_14_road, jame_14_water, jame_18_10_crop, jame_18_10_rc, jame_18_canopy, jame_18_other, jame_18_road, jame_18_water)
jame14_df <-
as.data.frame(jame_14) %>%
rename(
terrain = USGS_1_n38w077_20170509.tif )%>%
cbind(., jame14) %>%
na.omit()
jame18_df <-
as.data.frame(jame_18) %>%
rename(
terrain = USGS_1_n38w077_20170509.tif) %>%
cbind(., jame18)%>%
na.omit()
saveRDS(jame14_df, "~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/output/jame14_df.rds")
saveRDS(jame18_df, "~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/output/jame18_df.rds")
#############################################################################################################################
############################################# -------------------- ########################################################
############################################# | ISLE of WIGHT | ########################################################
############################################# -------------------- ########################################################
#############################################################################################################################
# Road
isle_14_road <- isle_14_10_crop %>%
mutate(road = as.numeric(islelc_14_10x10.tif == 9))
isle_18_road <- isle_18_10_crop %>%
mutate(road = as.numeric(islelc_18_10x10.tif == 9))
road_14 <- calc_focal_mean(isle_14_road, "road", 3)
road_18 <- calc_focal_mean(isle_18_road, "road", 3)
# Canopy
isle_14_canopy <- isle_14_10_crop %>%
mutate(canopy = as.numeric(islelc_14_10x10.tif == 3))
isle_18_canopy <- isle_18_10_crop %>%
mutate(canopy = as.numeric(islelc_18_10x10.tif == 3))
canopy_14_mean <- calc_focal_mean(isle_14_canopy, "canopy", 3)
canopy_18_mean <- calc_focal_mean(isle_18_canopy, "canopy", 3)
# Shrub
isle_14_shrub <- isle_14_10_crop %>%
mutate(shrub = as.numeric(islelc_14_10x10.tif == 2))
isle_18_shrub <- isle_18_10_crop %>%
mutate(shrub = as.numeric(islelc_18_10x10.tif == 2))
shrub_14_mean <- calc_focal_mean(isle_14_shrub, "shrub", 3)
shrub_18_mean <- calc_focal_mean(isle_18_shrub, "shrub", 3)
# Water
isle_14_water <- isle_14_10_crop %>%
mutate(water = as.numeric(islelc_14_10x10.tif == 1))
isle_18_water <- isle_18_10_crop %>%
mutate(water = as.numeric(islelc_18_10x10.tif == 1))
water_14_mean <- calc_focal_mean(isle_14_water, "water", 25)
water_18_mean <- calc_focal_mean(isle_18_water, "water", 25)
# Other
isle_14_other <- isle_14_10_crop %>%
mutate(other = as.numeric(islelc_14_10x10.tif == 8))
isle_18_other <- isle_18_10_crop %>%
mutate(other = as.numeric(islelc_18_10x10.tif == 8))
other_14_mean <- focal2(isle_14_other["other"], matrix(1, 3, 3), "mean")
other_14_mean <- focal2(other_14_mean["other"], matrix(1, 3, 3), "mean")
other_18_mean <- focal2(isle_18_other["other"], matrix(1, 3, 3), "mean")
other_18_mean<- focal2(other_18_mean["other"], matrix(1, 3, 3), "mean")
## join all the data
isle14 <- cbind(
as.data.frame(canopy_14_mean)['canopy'],
as.data.frame(road_14)['road'],
as.data.frame(other_14_mean)['other'],
as.data.frame(shrub_14_mean)['shrub'],
as.data.frame(water_14_mean)['water'],
as.data.frame(isle_14_pcnt_imperv)['lc'] %>%
rename(imperv = lc ),
as.data.frame(isle_change_rc)[c(5)]%>%
rename(lcchange = lc )
)
isle18 <- cbind(
as.data.frame(canopy_18_mean)['canopy'],
as.data.frame(road_18)['road'],
as.data.frame(other_18_mean)['other'],
as.data.frame(shrub_18_mean)['shrub'],
as.data.frame(water_18_mean)['water'],
as.data.frame(isle_18_pcnt_imperv)['lc'] %>%
rename(imperv = lc )
)
isle14 <- cbind(isle_14_10_crop,canopy_14_mean, road_14, other_14_mean, shrub_14_mean, water_14_mean, isle_14_pcnt_imperv, isle_change_rc,isle_change) # change impervious(0, 1, -1) 1 is targeted
rm(canopy_14_mean, road_14, other_14_mean, shrub_14_mean, water_14_mean, isle_14_pcnt_imperv, isle_change_rc)
isle18 <- cbind(isle_18_10_crop, canopy_18_mean, road_18,other_18_mean, shrub_18_mean, water_18_mean,isle_18_pcnt_imperv)
rm(canopy_18_mean, road_18, other_18_mean, shrub_18_mean, water_18_mean, isle_18_pcnt_imperv)
isle_14 <-
st_join(isle_14_10_rc,isle_tract) %>%
st_join(.,dem_isle)%>% # not changing
st_join(.,isle_slope) %>%
st_join(., soil_isle)
isle_18 <-
st_join(isle_18_10_rc,isle_tract2) %>%
st_join(.,dem_isle)%>% # not changing
st_join(.,isle_slope) %>%
st_join(., soil_isle)
rm(dem_isle,isle_slope, isle_14_10_crop, isle_14_10_rc, isle_14_canopy, isle_14_other, isle_14_road, isle_14_shrub, isle_18_10_crop, isle_18_10_rc, isle_18_canopy, isle_18_other, isle_18_road, isle_18_shrub)
isle14_df <-
as.data.frame(isle_14) %>%
rename(terrain = USGS_1_n38w077_20170509.tif )%>%
cbind(., isle14) %>%
na.omit()
isle18_df <-
as.data.frame(isle_18) %>%
rename(terrain = USGS_1_n38w077_20170509.tif) %>%
cbind(., isle18)%>%
na.omit()
saveRDS(isle14_df, "~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/output/isle14_df.rds")
saveRDS(isle18_df, "~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/output/isle18_df.rds")
#########################################################################################################################################
################################################### -------------------- ##############################################################
################################################### | | ##############################################################
################################################### | MODELING | ##############################################################
################################################### | | ##############################################################
################################################### -------------------- ##############################################################
#########################################################################################################################################
set.seed(717)
"%!in%" <- Negate("%in%")
isle14_df <- readRDS( "~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/output/isle14_df.rds")
jame14_df <- readRDS( "~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/output/jame14_df.rds")
port14_df <- readRDS( "~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/output/port14_df.rds")
# Data preparation
data <- data %>%
mutate(
lcre = case_when(lcchange == -1 ~ 0,
lcchange == 1 ~ 1,
lcchange == 0 ~ 0)
) %>%
mutate(
lcchange = as.factor(lcchange),
lcre = as.factor(lcre)
)
# Initial split for training and test
data_split <- initial_split(data, strata = "lcchange", prop = 0.8)
data_train <- training(data_split)
data_test <- testing(data_split)
apply_model_rf <- function(data) {
# Sample data
balanced_data <- data_train[c(sample(which(data_train$lcre == 0), sum(data_train$lcre == 1) *10) , which(data_train$lcre == 1)),]
# Cross-validation
cv_splits_geo <- group_vfold_cv(balanced_data, group = "GEOID")
# Create recipe
model_rec <- recipe(lcre ~ ., data = balanced_data) %>%
update_role(GEOID, new_role = "GEOID") %>% #78
update_role(lcchange, new_role = "lcchange") %>%
update_role(port_51740_landcover_2014.tif, new_role = "originallc") %>%
update_role(lc, new_role = "lc")# %>%
step_ns(x, y, options = list(df = 1))
# Model specifications
rf_plan <- rand_forest() %>%
set_args(mtry = tune()) %>%
set_args(min_n = tune()) %>% # 100,1000,seq=200
set_args(trees = tune()) %>% # 1000
#set_args(max_depth = 10) %>%
set_engine("ranger", importance = "impurity") %>%
set_mode("classification")
rf_grid <- expand.grid(mtry = c(5,10,15),
min_n = c(100,500,900),
trees = c(1000,1500)
)
# Create the workflow
rf_wf <-
workflow() %>%
add_recipe(model_rec) %>%
add_model(rf_plan)
# Tune hyperparameters
control <- control_resamples(save_pred = TRUE, verbose = TRUE)
metrics <- metric_set(f_meas)
rf_tuned <- rf_wf %>%
tune_grid(resamples = cv_splits_geo,
grid = rf_grid,
control = control,
metrics = metrics)
# Select best model
rf_best_params <- select_best(rf_tuned, metric = "f_meas")
rf_best_wf <- finalize_workflow(rf_wf, rf_best_params)
return(rf_best_wf)
}
# Fit multiple models
num_models <- 5
predict_dfs <- list()
rf_wfs <- list()
for (i in 1:num_models) {
# Split data
rf_wf <- apply_model_rf(data_train)
# Make predictions
rf_full_wf <- rf_wf %>%
fit(data)
predict_df <-
predict(rf_full_wf , new_data = data, type = "prob")
# Add to list
predict_dfs[[i]] <- predict_df[2]
rf_wfs[[i]] <- rf_full_wf
}
# Apply model to three different datasets
results_isle<- apply_model(isle14_df)
results_port<- apply_model(port14_df)
results_jame <- apply_model(jame14_df)
#########################################################################################################################################
################################################### -------------------- ##############################################################
################################################### | | ##############################################################
################################################### | PREDICTING | ##############################################################
################################################### | | ##############################################################
################################################### -------------------- ##############################################################
#########################################################################################################################################
isle18_df <- readRDS("~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/output/isle18_df.rds")
port18_df <- readRDS("~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/output/port18_df.rds")
jame18_df <- readRDS("~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/output/jame18_df.rds")
#############################################################################################################################
############################################# -------------------- ########################################################
############################################# | JAME CITY | ########################################################
############################################# -------------------- ########################################################
#############################################################################################################################
# Fit the best model to the whole dataset
full_fit_rf <- results_jame[1][2]%>%
fit(data = jame14_df)
# See the prediction for the full dataset
predict_df <- predict(full_fit_rf, new_data = jame14_df)
predict_df2 <- cbind(jame14_df,predict_df) %>%
mutate(error = as.numeric(.pred_class) - as.numeric(lcre))
# Use the best model to predict for the future
predict_df3 <- predict(full_fit_rf, new_data = jame18_df %>% mutate(lcchange = as.factor(lc)))
predict_df3 <- cbind(jame18_df,predict_df3)
saveRDS(predict_df3,'~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/output/predict_DF3_jame.rds')
# extract final model object
rf_full_mod <- extract_fit_parsnip(full_fit_rf)
saveRDS(rf_full_mod,'~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/output/best_rf1_jame.rds')
imp <- importance(rf_full_mod$fit, type = 1)
if (is.matrix(imp)) {
imp_df <- data.frame(variable = rownames(imp), importance = imp[, 1])
} else {
imp_df <- data.frame(variable = names(imp), importance = imp)
}
ggplot(imp_df, aes(x = reorder(variable, importance), y = importance, fill = "#41b6c4", alpha=0.5)) +
geom_bar(stat = "identity") +
coord_flip() +
scale_fill_identity() +
labs(x = "Variable", y = "Importance") +
ggtitle("Variable Importance")
#############################################################################################################################
############################################# -------------------- ########################################################
############################################# | PORTMOUTH | ########################################################
############################################# -------------------- ########################################################
#############################################################################################################################
# Fit the best model to the whole dataset
full_fit_rf <- results_port[1][2]%>%
fit(data = port14_df)
# See the prediction for the full dataset
predict_df <- predict(full_fit_rf, new_data = port14_df)
predict_df2 <- cbind(port14_df,predict_df) %>%
mutate(error = as.numeric(.pred_class) - as.numeric(lcre))
# Use the best model to predict for the future
predict_df3 <- predict(full_fit_rf, new_data = port18_df %>% mutate(lcchange = as.factor(lc)))
predict_df3 <- cbind(port18_df,predict_df3)
saveRDS(predict_df3,'~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/output/predict_DF3_port.rds')
# extract final model object
rf_full_mod <- extract_fit_parsnip(full_fit_rf)
saveRDS(rf_full_mod,'~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/output/best_rf1_port.rds')
#############################################################################################################################
############################################# -------------------- ########################################################
############################################# | ISLE OF WIGHT | ########################################################
############################################# -------------------- ########################################################
#############################################################################################################################
# Fit the best model to the whole dataset
full_fit_rf <- results_jame[1][2]%>%
fit(data = port14_df)
# See the prediction for the full dataset
predict_df <- predict(full_fit_rf, new_data = isle14_df)
predict_df2 <- cbind(isle14_df,predict_df) %>%
mutate(error = as.numeric(.pred_class) - as.numeric(lcre))
# Use the best model to predict for the future
predict_df3 <- predict(full_fit_rf, new_data = isle18_df %>% mutate(lcchange = as.factor(lc)))
predict_df3 <- cbind(isle18_df,predict_df3)
saveRDS(predict_df3,'~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/output/predict_DF3_isle.rds')
# extract final model object
rf_full_mod <- extract_fit_parsnip(full_fit_rf)
saveRDS(rf_full_mod,'~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/output/best_rf1_isle.rds')
#########################################################################################################################################
################################################### -------------------- ##############################################################
################################################### | | ##############################################################
################################################### | MAPPING | ##############################################################
################################################### | | ##############################################################
################################################### -------------------- ##############################################################
#########################################################################################################################################
predict_df2<- readRDS('~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/output/predict_DF3_port.rds')
s <- st_as_stars(predict_df2,
dimensions=st_dimensions(
x=sort(unique(df$x)),
y=sort(unique(df$y)),
point=TRUE),
dims=c('x','y'))
st_crs(s) <- st_crs(port_14)
s <- s%>%
st_transform(4326)
x <- s['.pred_class']
x.or <-s['lcre']
error <- s['error']
thresh_value <- 1
x[x != thresh_value] <- NA
x_sf <- st_union(st_as_sf(x))
# write the sf object to a GeoJSON file
geojson_path <- "~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/output/port_predict_xgb.geojson"
st_write(x_sf, geojson_path)
predict_df2<- readRDS('~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/output/predict_DF3_port.rds')
s <- st_as_stars(predict_df2,
dimensions=st_dimensions(
x=sort(unique(df$x)),
y=sort(unique(df$y)),
point=TRUE),
dims=c('x','y'))
st_crs(s) <- st_crs(port_18)
s <- s%>%
st_transform(4326)
x <- s['.pred_class']
x.or <-s['lcre']
error <- s['error']
thresh_value <- 1
x[x != thresh_value] <- NA
x_sf <- st_union(st_as_sf(x))
# write the sf object to a GeoJSON file
geojson_path <- "~/Github/Precision-Forecasts-of-Land-Cover-Change/Data/output/port_test_4326.geojson"
st_write(x_sf, geojson_path)
LS0tDQp0aXRsZTogIlByZWNpc2lvbiBGb3JlY2FzdHMgb2YgTGFuZCBDb3ZlciBDaGFuZ2UiDQpzdWJ0aXRsZTogIkNoZXNhcGVha2UgV2F0ZXJzaGVkIg0KYXV0aG9yOiAiWXVld2VuIERhaSwgU2h1amluZyBZaSwgWGluZ2UgWmhhbmciDQpkYXRlOiAiMjAyMy0wNC0yNSINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiAiaGlkZSINCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpgYGANCg0KW1JldHVybiB0byBNVVNBIDgwMSBQcm9qZWN0cyBQYWdlXShodHRwczovL3Blbm5tdXNhLmdpdGh1Yi5pby9NVVNBXzgwMS5pby8pDQoNClRoaXMgcHJvamVjdCB3YXMgY29tcGxldGVkIGZvciB0aGUgTVVTQS9TbWFydCBDaXRpZXMgUHJhY3RpY3VtIGNvdXJzZSAoTVVTQSA4MDEpIGluc3RydWN0ZWQgYnkgTWljaGFlbCBGaWNobWFuIGFuZCBNYXR0aGV3IEhhcnJpcy4gV2UgYXJlIGdyYXRlZnVsIHRvIG91ciBpbnN0cnVjdG9ycyBmb3IgdGhlaXIgY29udGludWVkIHN1cHBvcnQgYW5kIGZlZWRiYWNrLiBXZSB3b3VsZCBsaWtlIHRvIGdpdmUgc3BlY2lhbCB0aGFua3MgdG8gS0MgRmlsaXBwaW5vIGFuZCBCZW4gTWNGYXJsYW5lIGZyb20gSGFtcHRvbiBSb2FkcyBQbGFubmluZyBEaXN0cmljdCBDb21taXNzaW9uLCBhbmQgRGV4dGVyIExvY2tlIGZyb20gdGhlIFVuaXRlZCBTdGF0ZXMgRm9yZXN0IFNlcnZpY2UgZm9yIHByb3ZpZGluZyBkYXRhLCBpbnNpZ2h0LCBhbmQgc3VwcG9ydCB0aHJvdWdob3V0IHRoZSBzZW1lc3Rlci4gVGhpcyBwcm9qZWN0IHdvdWxkIG5vdCBoYXZlIGJlZW4gcG9zc2libGUgd2l0aG91dCB0aGVtLg0KDQpbVmlldyBEYXNoYm9hcmRdKGh0dHBzOi8veXVld2VuZGFpLmdpdGh1Yi5pby9NVVNBLVByYWN0aWN1bS1XZWIvKQ0KDQojIyAxLkludHJvZHVjdGlvbg0KIyMjIDEuMSBBYnN0cmFjdA0KVGhpcyBwcm9qZWN0IGFpbXMgdG8gZGV2ZWxvcCBhIHByZWNpc2lvbiBmb3JlY2FzdCBtb2RlbCBmb3IgbGFuZCBjb3ZlciBjaGFuZ2UgYXQgdGhlIENoZXNhcGVha2UgV2F0ZXJzaGVkLiBCeSBsZXZlcmFnaW5nIGhpZ2gtcmVzb2x1dGlvbiBsb25naXR1ZGluYWwgbGFuZCBjb3ZlciBkYXRhIHByb3ZpZGVkIGJ5IHRoZSBDaGVzYXBlYWtlIENvbnNlcnZhbmN5LCB0aGUgbW9kZWwgd2lsbCBwcmVkaWN0IGxhbmQgY292ZXIgY29udmVyc2lvbnMgZnJvbSBwZXJ2aW91cyB0byBpbXBlcnZpb3VzIHN1cmZhY2VzLiBUaGlzIGZvcmVjYXN0IHdpbGwgZW5hYmxlIGxhbmQgdXNlIGFuZCBlbnZpcm9ubWVudGFsIHBsYW5uZXJzIHRvIGlkZW50aWZ5IHdoZXJlIHVyYmFuIGdyb3d0aCB3aWxsIG9jY3VyLCBwcm9wb3NlIGdyZWVuIGluZnJhc3RydWN0dXJlIGFjY29yZGluZ2x5LCBhbmQgcHJpb3JpdGl6ZSBsYW5kcyBmb3IgcHJvdGVjdGlvbi4gVGhlIG1vZGVsIHdpbGwgYmUgZ2VuZXJhbGl6YWJsZSB0byB0aGUgY291bnR5IGxldmVsLCBpbmNvcnBvcmF0aW5nIG9ubHkgd2lkZWx5IGF2YWlsYWJsZSBpbnB1dHMsIHRodXMgYWxsb3dpbmcgYW55IG11bmljaXBhbGl0eSB3aXRoaW4gdGhlIENoZXNhcGVha2UgYmFzaW4gdG8gcmVwbGljYXRlIHRoZSBhbmFseXNpcy4gVGhpcyBwcm9vZi1vZi1jb25jZXB0IHByb2plY3Qgd2lsbCBkZW1vbnN0cmF0ZSB0aGUgdXRpbGl0eSBvZiBwcmVjaXNpb24gY29uc2VydmF0aW9uIGluIGxhbmQgcHJvdGVjdGlvbiBhbmQgZ3JlZW4gaW5mcmFzdHJ1Y3R1cmUgcGxhbm5pbmcgYW5kIHByb3ZpZGUgYSB2YWx1YWJsZSB0b29sIGZvciBwbGFubmVycyBhbmQgcG9saWN5bWFrZXJzIGFjcm9zcyB0aGUgcmVnaW9uLg0KDQojIyMgMS4yIEJhY2tncm91bmQgDQpUaGUgQ2hlc2FwZWFrZSBCYXkgd2F0ZXJzaGVkIGlzIGFuIGVjb2xvZ2ljYWxseSBhbmQgZWNvbm9taWNhbGx5IHNpZ25pZmljYW50IHJlc291cmNlLCBlbmNvbXBhc3NpbmcgZGl2ZXJzZSBlY29zeXN0ZW1zIGFuZCBzdXBwb3J0aW5nIGEgbXVsdGl0dWRlIG9mIGluZHVzdHJpZXMsIGluY2x1ZGluZyBhZ3JpY3VsdHVyZSwgdG91cmlzbSwgYW5kIGZpc2hlcmllcy4gSG93ZXZlciwgdGhlIHJlZ2lvbiBpcyBmYWNpbmcgaW5jcmVhc2luZyBlbnZpcm9ubWVudGFsIGNoYWxsZW5nZXMgZHVlIHRvIHRoZSBjb21iaW5lZCBlZmZlY3RzIG9mIHNlYS1sZXZlbCByaXNlIGFuZCBsYW5kIHN1YnNpZGVuY2UuIEFzIGEgcmVzdWx0LCB0aGUgYXJlYSBoYXMgYmVjb21lIHRoZSBzZWNvbmQtbW9zdCB2dWxuZXJhYmxlIHJlZ2lvbiBpbiB0aGUgbmF0aW9uIHRvIGZsb29kaW5nIGFuZCBzdG9ybSBzdXJnZSwgb25seSBhZnRlciBOZXcgT3JsZWFucy4gUHJlZGljdGluZyBsYW5kIGNvdmVyIGNoYW5nZXMsIHBhcnRpY3VsYXJseSB0aGUgY29udmVyc2lvbiBmcm9tIHBlcnZpb3VzIHRvIGltcGVydmlvdXMgc3VyZmFjZXMsIGlzIGNydWNpYWwgaW4gYWRkcmVzc2luZyB0aGVzZSBjaGFsbGVuZ2VzIGFuZCBpbmZvcm1pbmcgY2xpbWF0ZSBhZGFwdGF0aW9uIGFuZCBtaXRpZ2F0aW9uIHBsYW5uaW5nLg0KDQpPdXIgcHJvamVjdCBmb2N1c2VzIG9uIHRocmVlIGRpc3RpbmN0IGNvdW50aWVzIHdpdGhpbiB0aGUgQ2hlc2FwZWFrZSBCYXkgd2F0ZXJzaGVkLCByZXByZXNlbnRpbmcgdmFyeWluZyBkZXZlbG9wbWVudCBjb250ZXh0cy4gUG9ydHNtb3V0aCBpcyB0aGUgdXJiYW4gcHJvdG90eXBlIGNoYXJhY3Rlcml6ZWQgYnkgaXRzIGRlbnNlIHJlc2lkZW50aWFsLCBjb21tZXJjaWFsLCBhbmQgaW5kdXN0cmlhbCBhcmVhcy4gSmFtZXMgQ2l0eSBDb3VudHkgZXhlbXBsaWZpZXMgYSBzdWJ1cmJhbiBjb250ZXh0LCB3aXRoIGEgbWl4IG9mIHJ1cmFsLCBzdWJ1cmJhbiwgYW5kIHVyYmFuIGRldmVsb3BtZW50IGFuZCBhIGRpdmVyc2UgbGFuZHNjYXBlIGVuY29tcGFzc2luZyBmb3Jlc3RzLCB3ZXRsYW5kcywgYW5kIGhpc3RvcmljIHNpdGVzLiBMYXN0bHksIElzbGUgb2YgV2lnaHQgQ291bnR5IHJlcHJlc2VudHMgdGhlIHJ1cmFsIGFzcGVjdCwgcHJlZG9taW5hbnRseSBjaGFyYWN0ZXJpemVkIGJ5IGFncmljdWx0dXJlLCBmb3Jlc3RyeSwgYW5kIGV4dGVuc2l2ZSBuYXR1cmFsIGhhYml0YXRzLiBCeSBjb25zaWRlcmluZyB0aGVzZSBkaXZlcnNlIGNvdW50aWVzLCB3ZSBjYW4gZGV2ZWxvcCBhIGNvbXByZWhlbnNpdmUgYW5kIGdlbmVyYWxpemFibGUgbW9kZWwgdG8gcHJlZGljdCBsYW5kIGNvdmVyIGNoYW5nZXMgYWNyb3NzIHZhcmlvdXMgcmVnaW9uYWwgZGV2ZWxvcG1lbnQgc2NlbmFyaW9zLg0KDQohW10oaW1hZ2VzL0hSUERDLmpwZykNCg0KDQojIyMgMS4zIE1vdGl2YXRpb24gJiBVc2UgQ2FzZQ0KDQpCdWlsZGluZyByZXNpbGllbnQgY29tbXVuaXRpZXMgaXMgYSB0b3AgcHJpb3JpdHkgZm9yIHRoZSBIYW1wdG9uIFJvYWRzIFBsYW5uaW5nIERpc3RyaWN0IENvbW1pc3Npb24gKEhSUERDKS4gVG8gc3VwcG9ydCB0aGlzIGdvYWwsIHRoZSBIUlBEQyBoYXMgZXN0YWJsaXNoZWQgYSBncmVlbiBpbmZyYXN0cnVjdHVyZSBwbGFuIHRoYXQgc2Vla3MgdG8gaWRlbnRpZnkgYW5kIHByaW9yaXRpemUgYSBuZXR3b3JrIG9mIHZhbHVhYmxlIGNvbnNlcnZhdGlvbiBsYW5kcy4gVGhpcyBwbGFuIGFpbXMgdG8gYWNoaWV2ZSBtdWx0aXBsZSBiZW5lZml0cywgc3VjaCBhcyBoYWJpdGF0IHByb3RlY3Rpb24sIGRyaW5raW5nIHdhdGVyIHN1cHBseSBwcm90ZWN0aW9uLCBzdG9ybXdhdGVyIG1hbmFnZW1lbnQsIGFuZCByZWNyZWF0aW9uYWwgb3Bwb3J0dW5pdGllcy4NCg0KQSBjcnVjaWFsIGNvbXBvbmVudCBvZiB0aGlzIHBsYW4gaW52b2x2ZXMgZGV2ZWxvcGluZyBhIG1vZGVsIHRvIGZvcmVjYXN0IHBvdGVudGlhbCBmdXR1cmUgZ3Jvd3RoIGFuZCBpZGVudGlmeSBhcmVhcyBvZiB0aGUgZ3JlZW4gaW5mcmFzdHJ1Y3R1cmUgbmV0d29yayB0aGF0IGFyZSBtb3N0IGF0IHJpc2sgZm9yIGRldmVsb3BtZW50LiBPdXIgcHJvamVjdCBhaW1zIHRvIGNyZWF0ZSBhIGZvcmVjYXN0IHRoYXQgZW5hYmxlcyBsYW5kIHVzZSBhbmQgZW52aXJvbm1lbnRhbCBwbGFubmVycyB0byBwaW5wb2ludCB3aGVyZSB1cmJhbiBncm93dGggaXMgbGlrZWx5IHRvIG9jY3VyLCBwcm9wb3NlIGdyZWVuIGluZnJhc3RydWN0dXJlIGFjY29yZGluZ2x5LCBhbmQgcHJpb3JpdGl6ZSBsYW5kcyBmb3IgcHJvdGVjdGlvbi4gDQoNClRoaXMgcHJvb2Ytb2YtY29uY2VwdCBwcm9qZWN0IGRlbW9uc3RyYXRlcyB0aGUgdXRpbGl0eSBvZiBwcmVjaXNpb24gY29uc2VydmF0aW9uIGluIGxhbmQgcHJvdGVjdGlvbiBhbmQgZ3JlZW4gaW5mcmFzdHJ1Y3R1cmUgcGxhbm5pbmcsIHByb3ZpZGluZyBhIHZhbHVhYmxlIHRvb2wgZm9yIHBsYW5uZXJzIGFuZCBwb2xpY3ltYWtlcnMgYWNyb3NzIHRoZSByZWdpb24uIEZvciBleGFtcGxlLCBBbmRyZXcsIHRoZSBoZWFkIG9mIHRoZSBHcmVlbiBJbmZyYXN0cnVjdHVyZSBUZWFtIGZyb20gQ2hlc2FwZWFrZSBDb25zZXJ2YW5jeSwgYW5kIGhpcyB0ZWFtIHdpbGwgdXNlIG91ciB3ZWIgYXBwIHRvIG1ha2UgaW5mb3JtZWQgZGVjaXNpb25zIG9uIHdoaWNoIHJlZ2lvbnMgaGF2ZSB0aGUgaGlnaGVzdCBwcmlvcml0eSB0byByZWNlaXZlIGZ1bmRpbmcuDQoNCiFbXShpbWFnZXMvdXNlX2Nhc2UucG5nKQ0KDQoNCiMjIDIuIERhdGEgYW5kIE1ldGhvZHMNCg0KIyMjIDIuMSBVbmRlcnN0YW5kaW5nIExhbmQgQ292ZXIgZGF0YQ0KVGhlIENoZXNhcGVha2UgQ29uc2VydmFuY3kgcHJvdmlkZWQgaGlnaC1yZXNvbHV0aW9uIGxhbmQgY292ZXIgZGF0YSBmb3IgMjAxMy8xNCBhbmQgMjAxNy8xOC4gVGhpcyB2YXN0IHJhc3RlciBkYXRhc2V0IGJvYXN0cyBhbiBpbXByZXNzaXZlIDEtbWV0ZXIgYWNjdXJhY3ksIG9mZmVyaW5nIDkwMCB0aW1lcyBtb3JlIGRldGFpbCB0aGFuIHRoZSBjb21tb25seSB1c2VkIDMwLW1ldGVyIHJlc29sdXRpb24gTmF0aW9uYWwgTGFuZCBDb3ZlciBEYXRhc2V0LiBTdWNoIGEgbGV2ZWwgb2YgZGV0YWlsIGlzIGNydWNpYWwgZm9yIGNhcHR1cmluZyBzdWJ0bGUgY2hhbmdlcyBpbiBsYW5kIGNvdmVyLg0KDQpUaGUgbGFuZCBjb3ZlciBjbGFzc2lmaWNhdGlvbiBpbmNsdWRlcyBwZXJ2aW91cyBzdXJmYWNlcyBzdWNoIGFzIHRyZWUgY2Fub3BpZXMgYW5kIHNocnVicywgd2hpY2ggYWxsb3cgd2F0ZXIgdG8gaW5maWx0cmF0ZSB0aGUgZ3JvdW5kLiBJbiBjb250cmFzdCwgaW1wZXJ2aW91cyBzdXJmYWNlcyBlbmNvbXBhc3MgY2F0ZWdvcmllcyBsaWtlIHJvYWRzIGFuZCBzdHJ1Y3R1cmVzIHRoYXQgcHJldmVudCB3YXRlciBpbmZpbHRyYXRpb24sIGxlYWRpbmcgdG8gaW5jcmVhc2VkIHJ1bm9mZiBhbmQgcG90ZW50aWFsIGZsb29kaW5nIGlzc3Vlcy4gRXZlbiB0aG91Z2ggd2F0ZXIgYW5kIHdldGxhbmQgYXJlIG9mdGVuIGNvbnNpZGVyZWQgaW1wZXJ2aW91cyBzdXJmYWNlcywgaW4gdGhpcyBzdHVkeSwgd2UgY2xhc3NpZnkgdGhlbSBhcyBwZXJ2aW91cyBzdXJmYWNlcyBkdWUgdG8gdGhlaXIgZHluYW1pYyBuYXR1cmUsIGludGVyYWN0aW9uIHdpdGggZ3JvdW5kd2F0ZXIsIGZsb29kcGxhaW4gY29ubmVjdGl2aXR5LCBhbmQgdGhlIGNyaXRpY2FsIGZ1bmN0aW9ucyBvZiB3ZXRsYW5kcyBpbiB3YXRlciBzdG9yYWdlIGFuZCBpbmZpbHRyYXRpb24uIA0KDQohW10oaW1hZ2VzL0RhdGEucG5nKQ0KDQpbRGF0YSBTb3VyY2VdKGh0dHBzOi8vd3d3LmNoZXNhcGVha2Vjb25zZXJ2YW5jeS5vcmcvY29uc2VydmF0aW9uLWlubm92YXRpb24tY2VudGVyL2hpZ2gtcmVzb2x1dGlvbi1kYXRhL2x1bGMtZGF0YS1wcm9qZWN0LTIwMjIvKQ0KDQoNCiMjIyAyLjIgT2h0ZXIgZGF0YQ0KVG8gdW5kZXJzdGFuZCBob3cgbGFuZGNvdmVyIGNoYW5nZSBpcyBhZmZlY3RlZCBieSBvdGhlciBlbnZpcm9ubWVudGFsLCBzb2NpYWwgYW5kIGVjb25vbWljYWwgZmFjdG9ycywgd2UgYWxzbyBhY3F1aXJlIGRhdGEgZnJvbSB0aGUgZm9sbG93aW5nIHNvdXJjZTogDQoNCiogW0RFTSAoIDEgYXJjLXNlY29uZCkgZnJvbSBVU0dTXShodHRwczovL2FwcHMubmF0aW9uYWxtYXAuZ292L2Rvd25sb2FkZXIvKQ0KDQoqIFtTb2lsIERhdGEgZnJvbSB0aGUgV2ViIFNvaWwgU3VydmV5XShodHRwczovL3dlYnNvaWxzdXJ2ZXkubnJjcy51c2RhLmdvdi9hcHAvKQ0KDQoqIGNlbnN1cyB0cmFjdC1sZXZlbCBkYXRhICgyMDE0LCAyMDE4LCAyMDIxKSBmcm9tIGZvdXIgeWVhcnMgb2YgdGhlIEFtZXJpY2FuIENvbW11bml0eSBTdXJ2ZXkgKEFDUykgDQoNCiMjIyAyLjMgVW5pdCBvZiBhbmFseXNpcw0KVG8gZmFjaWxpdGF0ZSBvdXIgZnV0dXJlIGFuYWx5c2lzIGFuZCBlbnN1cmUgY29uc2lzdGVuY3ksIHdlIGdhdGhlcmVkIGFuZCByZXNhbXBsZWQgYWxsIGRhdGEgdG8gYSAxMCB4IDEwLW1ldGVyIHJlc29sdXRpb24gYXMgdGhlIGJhc2ljIGFuYWx5c2lzIHVuaXQuIFdlIG9wdGVkIGZvciBhIDEwLW1ldGVyIHJlc29sdXRpb24gYXMgaXQgcHJvdmlkZXMgc3VmZmljaWVudCBkZXRhaWwgZm9yIHBsYW5uaW5nIHB1cnBvc2VzIHdoaWxlIG1pbmltaXppbmcgbm9pc2UgYW5kIHJlZHVjaW5nIHRoZSBkYXRhc2V0IHNpemUsIHRoZXJlYnkgZW5hYmxpbmcgYSBmYXN0ZXIgY2FsY3VsYXRpb24gcHJvY2Vzcy4gDQoNCg0KIVtdKGltYWdlcy9tZXRob2QucG5nKQ0KDQoNCg0KDQojIyAzLiBFeHBsb3JhdG9yeSBBbmFseXNpcw0KDQojIyMgMy4xIExhbmQgQ292ZXIgVHlwZSBhbmQgQ2hhbmdlIER5bmFtaWNzDQpXZSBiZWdhbiBieSBjb21wYXJpbmcgdGhlIGxhbmQgY292ZXIgcGF0dGVybnMgYW5kIGNoYW5nZXMgYWNyb3NzIHRoZSB0aHJlZSBjb3VudGllcy4gVGhpcyBjb21wYXJpc29uIGhlbHBlZCB1cyBpZGVudGlmeSBlYWNoIGNvdW50eSdzIHVuaXF1ZSBjaGFyYWN0ZXJpc3RpY3MgYW5kIHRyZW5kcywgcHJvdmlkaW5nIGluc2lnaHRzIGludG8gaG93IHVyYmFuLCBzdWJ1cmJhbiwgYW5kIHJ1cmFsIGNvbnRleHRzIGFmZmVjdGVkIGxhbmQgY292ZXIgY29udmVyc2lvbi4gTGFuZCBjb3ZlciBjaGFuZ2VzIGFyZSBoaWdobHkgcmVsYXRlZCB0byB0aGUgZXhpc3RpbmcgbGFuZCBjb3ZlciB0eXBlLiBGb3IgSmFtZXMgQ2l0eSBhbmQgSXNsZSBvZiBXaWdodCwgdHJlZSBjYW5vcHkgaXMgdGhlIGxhbmQgY292ZXIgdHlwZSB0aGF0IHVuZGVyZ29lcyB0aGUgbW9zdCBjaGFuZ2UsIHdoaWxlIGZvciBQb3J0c21vdXRoLCBsb3cgdmVnZXRhdGlvbiBleHBlcmllbmNlcyB0aGUgbW9zdCBzaWduaWZpY2FudCBjaGFuZ2UuDQoNCiFbXShpbWFnZXMvbGFuZGNvdmVyLnBuZykNCg0KIyMjIDMuMiBFbnZpcm9ubWVudGFsIEZhY3RvcnMNCg0KRW52aXJvbm1lbnRhbCBmYWN0b3JzIHBsYXllZCBhIHNpZ25pZmljYW50IHJvbGUgaW4gbGFuZCBjb3ZlciBjaGFuZ2VzLiBXZSBleGFtaW5lZCBzaXRlIGNoYXJhY3RlcmlzdGljcyB0aGF0IHJlbWFpbmVkIGNvbnN0YW50IG92ZXIgdGltZSwgc3VjaCBhcyBlbGV2YXRpb24sIHNsb3BlLCBhbmQgc29pbCB0eXBlLCB0byB1bmRlcnN0YW5kIHRoZWlyIGluZmx1ZW5jZSBvbiBsYW5kIGNvdmVyIGNvbnZlcnNpb24gcGF0dGVybnMuIFVuZGVyc3RhbmRpbmcgdGhlc2Ugc3RhdGljIGZhY3RvcnMgaGVscGVkIHVzIHByZWRpY3QgaG93IGxhbmQgY292ZXIgbWlnaHQgZXZvbHZlIGluIGRpZmZlcmVudCBlbnZpcm9ubWVudGFsIHNldHRpbmdzLg0KDQpUYWtlIFBvcnRzbW91dGggY291bnR5IGFzIGV4YW1wbGUsIHRoZSBwbG90IGJlbG93IGRlbW9uc3RyYXRlcyB0aGF0IHRoZSBtZWFuIHNsb3BlIGluIGFyZWFzIHdoZXJlIGxhbmQgY292ZXIgY2hhbmdlZCBmcm9tIHBlcnZpb3VzIHRvIGltcGVydmlvdXMgYmV0d2VlbiAyMDE0IGFuZCAyMDE4ICgxKSBpcyBzaWduaWZpY2FudGx5IGhpZ2hlciB0aGFuIGluIGFyZWFzIHRoYXQgZGlkIG5vdCBjaGFuZ2Ugb3IgY2hhbmdlZCBpbiB0aGUgb3Bwb3NpdGUgZGlyZWN0aW9uICgwKS4NCg0KIVtdKGltYWdlcy9lbnZpcm9ubWVudC5wbmcpDQoNCiMjIyAzLjMgU29jaWFsIGFuZCBFY29ub21pY2FsIEZhY3RvcnMNClNvY2lhbCBhbmQgZWNvbm9taWMgZmFjdG9ycywgd2hpY2ggY2hhbmdlIG92ZXIgdGltZSwgYWxzbyBpbXBhY3QgbGFuZCBjb3ZlciBjaGFuZ2VzLiBXZSBpbnZlc3RpZ2F0ZWQgdmFyaWFibGVzIHN1Y2ggYXMgcG9wdWxhdGlvbiBncm93dGgsIGVjb25vbWljIGRldmVsb3BtZW50LCBhbmQgZGVtb2dyYXBoaWMgY2hhbmdlcyB0byB1bmRlcnN0YW5kIGhvdyB0aGVzZSBmYWN0b3JzIGNvbnRyaWJ1dGVkIHRvIGxhbmQgY292ZXIgY29udmVyc2lvbi4gQnkgaW5jb3Jwb3JhdGluZyB0aGVzZSBkeW5hbWljIGZhY3RvcnMgaW50byBvdXIgYW5hbHlzaXMsIHdlIHdlcmUgYWJsZSB0byBiZXR0ZXIgZm9yZWNhc3QgbGFuZCBjb3ZlciBjaGFuZ2VzIGJhc2VkIG9uIHBvdGVudGlhbCBmdXR1cmUgc2NlbmFyaW9zLg0KDQpUaGUgcGxvdHMgcHJlc2VudGVkIGhlcmUgaWxsdXN0cmF0ZSB0aGF0IHRoZSBwZXJjZW50YWdlIG9mIHdoaXRlIHBvcHVsYXRpb24gY2hhbmdlIGV4aGliaXRzIGEgZGlmZmVyZW50IHBhdHRlcm4gaW4gYXJlYXMgb2YgbGFuZCBjb3ZlciBjaGFuZ2UgY29tcGFyZWQgdG8gdGhlIG92ZXJhbGwgY291bnR5LiBUaGlzIG9ic2VydmF0aW9uIGluZGljYXRlcyB0aGF0IGluIFBvcnRzbW91dGggQ291bnR5LCBsYW5kIGNvdmVyIGNoYW5nZSBpcyBhbHNvIGFzc29jaWF0ZWQgd2l0aCBjaGFuZ2VzIGluIGNlbnN1cyBkYXRhLCBwYXJ0aWN1bGFybHkgdGhlIHBlcmNlbnRhZ2Ugb2Ygd2hpdGUgcG9wdWxhdGlvbiBjaGFuZ2UuDQoNCg0KIVtdKGltYWdlcy9zb2NpYWwucG5nKQ0KDQoNCg0KIyMgNC4gRmVhdHVyZSBFbmdpbmVlcmluZw0KDQojIyMgNC4xIFNwYXRpYWwgRWZmZWN0cw0KSW5jb3Jwb3JhdGluZyBzcGF0aWFsIHJlbGF0aW9uc2hpcHMgaW50byBvdXIgbW9kZWwgd2FzIGNydWNpYWwgZm9yIGNhcHR1cmluZyB0aGUgc3BhdGlhbCBpbmZsdWVuY2Ugb2Ygb3JpZ2luYWwgbGFuZCBjb3ZlciB0eXBlcyBvbiBsYW5kIGNvdmVyIGNoYW5nZS4gV2UgcGVyZm9ybWVkIGZvY2FsIHJhc3RlciBjYWxjdWxhdGlvbnMgYW5kIHNwYXRpYWwgbGFnIGNhbGN1bGF0aW9ucyB0byBjcmVhdGUgZmVhdHVyZXMgdGhhdCBhY2NvdW50ZWQgZm9yIHRoZSBzcGF0aWFsIGNvbnRleHQgb2YgbGFuZCBjb3ZlciBjb252ZXJzaW9uLiBUaGVzZSBlbmdpbmVlcmVkIGZlYXR1cmVzIGhlbHBlZCB1cyBkZXZlbG9wIGEgbW9yZSBhY2N1cmF0ZSBhbmQgcm9idXN0IHByZWRpY3RpdmUgbW9kZWwsIGNhcGFibGUgb2YgY2FwdHVyaW5nIHRoZSBudWFuY2VzIG9mIGxhbmQgY292ZXIgY2hhbmdlIGFjcm9zcyBkaXZlcnNlIGRldmVsb3BtZW50IGNvbnRleHRzLg0KDQohW10oaW1hZ2VzL2ZlYXR1cmVfZW5naW5lZXJpbmcucG5nKQ0KDQojIyMgNC4yIFBhaXJ3aXNlIENvcnJlbGF0aW9ucw0KVG8gc2VsZWN0IHZhcmlhYmxlcyBmb3Igb3VyIHByZWRpY3RpdmUgbW9kZWwsIHdlIHZpc3VhbGl6ZSBjb3JyZWxhdGlvbnMgYmV0d2VlbiBvdXIgbnVtZXJpYyByaXNrIGZhY3RvcnMuIFRoaXMgaGVscHMgdXMgZW5zdXJlIHRoYXQgb3VyIHZhcmlhYmxlcyBhcmUgbm90IGNvcnJlbGF0ZWQgd2l0aCBvbmUgYW5vdGhlci4NCg0KIVtdKGltYWdlcy9jb3JyZWxhdGlvbnBsb3QucG5nKQ0KDQojIyMgNC4zIEZpbmFsIEZlYXR1cmVzIA0KQmFzZWQgb24gdGhpcyBwbG90LCB3ZSBzZWxlY3QgdGhlIGZvbGxvd2luZyB2YXJpYWJsZXMgdG8gdXNlIGluIG91ciBtb2RlbDoNCiMjIyMgRGVwZW5kZW50IFZhcmlhYmxlDQoqIFdoZXRoZXIgdGhlIGxhbmQgY292ZXIgY2hhbmdlIGZyb20gaW1wZXJ2aW91cyB0byBwcmV2aW91cyANCg0KIyMjIyBJbmRlcGVuZGVudCBWYXJpYWJsZXMNCg0KKiBFeGlzdGluZyBsYW5kIGNvdmVyIHR5cGVzIA0KICAgICsgc2hydWINCiAgICArIHdhdGVyDQogICAgKyBjYW5vcHkNCiAgICArIHJvYWQNCiAgICArIG90aGVyIChvdGhlciBpbXBlcnZpb3VzIHN1cmZhY2UgYmVzaWRlcyByb2FkKQ0KICAgICsgaW1wZXJ2aW91cyBkZW5zaXR5DQoNCiogRW52aXJvbm1lbnRhbCBmYWN0b3JzDQogICAgKyB0ZXJyYWluIChFbGV2YXRpb24pDQogICAgKyBzbG9wZQ0KICAgICsgc29pbCB0eXBlDQoNCiogU29jaW8tZWNvbm9taWMgZmFjdG9ycyANCiAgICArIHBvcHVsYXRpb24gY2hhbmdlDQogICAgKyBwZXJjZW50IG9mIHdoaXRlIGNoYW5nZSANCiAgICArIHVuaXQgY2hhbmdlDQogICAgKyBtZWRpYW4gaG91c2Vob2xkIGluY29tZSBjaGFuZ2UgDQogICAgKyBhcmVhIG9mIGNlbnN1cyBibG9jayBncm91cA0KDQoqIFNwYXRpYWwgTGFnIGZhY3RvcnMgDQogICAgKyBub25saW5lYXIgdHJhbnNmb3JtYXRpb24gdG8gcHJlZGljdG9yIHgNCiAgICArIG5vbmxpbmVhciB0cmFuc2Zvcm1hdGlvbiB0byBwcmVkaWN0b3IgeSANCg0KDQoNCiMjIDUuIE1vZGVsaW5nICYgRXZhbHVhdGlvbiAoTmVlZCBDaGVjayEpDQoNCiMjIyA1LjEgTW9kZWwgQnVpbGRpbmcNClRvIGVuc3VyZSBjb21wdXRhdGlvbmFsIGVmZmljaWVuY3kgYW5kIHNjYWxhYmlsaXR5LCB3ZSBkb3duc2FtcGxlZCB0aGUgb3JpZ2luYWwgZGF0YXNldCB0byA1MDAsMDAwIGRhdGEgcG9pbnRzIGZvciBtb2RlbCBidWlsZGluZyBhbmQgdGhlbiBmaXR0ZWQgdGhlIHNlbGVjdGVkIG1vZGVsIGJhY2sgdG8gdGhlIHdob2xlIGRhdGFzZXQgZm9yIGZ1dHVyZSBwcmVkaWN0aW9ucy4gV2UgZW1wbG95ZWQgZ2VvIGNyb3NzLXZhbGlkYXRpb24gYXQgdGhlIGJsb2NrIGdyb3VwIGxldmVsIHRvIGVuc3VyZSB0aGUgcm9idXN0bmVzcyBvZiBvdXIgbW9kZWwgYW5kIGF2b2lkIG92ZXJmaXR0aW5nLg0KDQpQZXJmb3JtYW5jZSBldmFsdWF0aW9uIHdhcyBjb25kdWN0ZWQgdXNpbmcgdGhlIGNvbmZ1c2lvbiBtYXRyaXggZm9yIGJpbmFyeSB0aHJlc2hvbGQgc2V0dGluZyBhbmQgbW9kZWwgc2VsZWN0aW9uLiBUaGlzIGFwcHJvYWNoIGFsbG93ZWQgdXMgdG8gYXNzZXNzIHRoZSBhY2N1cmFjeSwgc2Vuc2l0aXZpdHksIGFuZCBzcGVjaWZpY2l0eSBvZiB0aGUgbW9kZWxzIGFuZCBjb21wYXJlIHRoZWlyIHBlcmZvcm1hbmNlLg0KDQohW10oaW1hZ2VzL3NhbXBsZS5wbmcpDQoNCiMjIyA1LjIgUmVmaW5lIGZvciBiZXR0ZXIgcHJlZGljdGlvbg0KDQoNCiMjIyA1LjMgTW9kZWwgVHlwZSBTZWxlY3Rpb24NCg0KUmVjb2duaXppbmcgdGhhdCBkaWZmZXJlbnQgdHlwZXMgb2YgbW9kZWxzIHBlcmZvcm0gd2VsbCBvbiBkaWZmZXJlbnQgZGF0YXNldHMsIHdlIGV4cGVyaW1lbnRlZCB3aXRoIHRocmVlIG1vZGVsIHR5cGVzIGZvciBwcmVkaWN0aW5nIGxhbmQgY292ZXIgY2hhbmdlOiBSYW5kb20gRm9yZXN0LCBYR0Jvb3N0LCBhbmQgQmlub21pYWwgR2VuZXJhbGl6ZWQgTGluZWFyIE1vZGVsIChHTE0pLiBUaGVzZSBtb2RlbHMgd2VyZSBjaG9zZW4gZHVlIHRvIHRoZWlyIGFiaWxpdHkgdG8gaGFuZGxlIGNvbXBsZXggaW50ZXJhY3Rpb25zIGFuZCBub24tbGluZWFyIHJlbGF0aW9uc2hpcHMgd2l0aGluIHRoZSBkYXRhLg0KDQpBZnRlciBldmFsdWF0aW5nIHRoZSBwZXJmb3JtYW5jZSBvZiBlYWNoIG1vZGVsIHR5cGUsIHdlIHNlbGVjdGVkIFJhbmRvbSBGb3Jlc3QgYXMgdGhlIG1vc3Qgc3VpdGFibGUgbW9kZWwgZm9yIG91ciBhbmFseXNpcywgYXMgaXQgZGVtb25zdHJhdGVkIHRoZSBiZXN0IGFjY3VyYWN5LiBSYW5kb20gRm9yZXN0IGlzIGFuIGVuc2VtYmxlIGxlYXJuaW5nIG1ldGhvZCB0aGF0IGJ1aWxkcyBtdWx0aXBsZSBkZWNpc2lvbiB0cmVlcyBhbmQgY29tYmluZXMgdGhlaXIgcmVzdWx0cyB0byBpbXByb3ZlIG92ZXJhbGwgYWNjdXJhY3kgYW5kIHN0YWJpbGl0eS4gVGhpcyBtb2RlbCBpcyBwYXJ0aWN1bGFybHkgd2VsbC1zdWl0ZWQgZm9yIGhhbmRsaW5nIGhpZ2gtZGltZW5zaW9uYWwgYW5kIG5vaXN5IGRhdGEsIG1ha2luZyBpdCBhbiBpZGVhbCBjaG9pY2UgZm9yIHByZWRpY3RpbmcgbGFuZCBjb3ZlciBjaGFuZ2VzIGluIG91ciBzdHVkeSBhcmVhLg0KDQohW10oaW1hZ2VzL21vZGVsX2NvbXBhcmUucG5nKQ0KDQoNCg0KDQoNCiMjIyA1LjQgTW9kZWwgRXZhbHVhdGlvbiAmIFZhbGlkYXRpb24NCg0Kcm9jDQoNCiFbXShpbWFnZXMvc2VuLnBuZykNCg0KDQojIyMgNS41IENvbXBhcmlzb24gYmV0d2VlbiBDb3VudGllcw0KVGhlIHBsb3RzIGJlbG93IGluZGljYXRlIHRoYXQgc3BhdGlhbCBsYWcgZmFjdG9ycyBwbGF5IGEgY3J1Y2lhbCByb2xlIGluIGxhbmQgY292ZXIgY2hhbmdlIHByZWRpY3Rpb24gZm9yIGFsbCB0aHJlZSBjb3VudGllcy4gSW4gYWRkaXRpb24sIHRlcnJhaW4sIHdhdGVyLCBzb2lsLCBhbmQgY2Fub3B5IGVtZXJnZSBhcyBpbXBvcnRhbnQgZmVhdHVyZXMgYWNyb3NzIEphbWVzIENpdHksIElzbGUgb2YgV2lnaHQsIGFuZCBQb3J0c21vdXRoIGNvdW50aWVzLiBGb3IgSmFtZXMgQ2l0eSBhbmQgSXNsZSBvZiBXaWdodCwgc2xvcGUgaXMgYWxzbyBhIHNpZ25pZmljYW50IGZlYXR1cmUsIHdoZXJlYXMgaXRzIGltcG9ydGFuY2UgaXMgcmVkdWNlZCBpbiBQb3J0c21vdXRoLiBUaGlzIGRpZmZlcmVuY2UgY2FuIGJlIGF0dHJpYnV0ZWQgdG8gdGhlIHVyYmFuIG5hdHVyZSBvZiBQb3J0c21vdXRoLCB3aGVyZSBsYW5kZm9ybXMgbGVzcyBpbmZsdWVuY2UgdXJiYW4gZ3Jvd3RoLg0KDQpJbiBQb3J0c21vdXRoLCBzb2NpYWwgYW5kIGVjb25vbWljIGZhY3RvcnMgc3VjaCBhcyB0aGUgcGVyY2VudGFnZSBvZiB3aGl0ZSBwb3B1bGF0aW9uIGNoYW5nZSBhbmQgbWVkaWFuIGhvdXNlaG9sZCBpbmNvbWUgZGVtb25zdHJhdGUgZ3JlYXRlciBzaWduaWZpY2FuY2UgaW4gcHJlZGljdGluZyBsYW5kIGNvdmVyIGNoYW5nZS4gVGhpcyBzdWdnZXN0cyB0aGF0IHVyYmFuIGdyb3d0aCBpbiBQb3J0c21vdXRoIGlzIG1vcmUgY2xvc2VseSB0aWVkIHRvIHNvY2lvZWNvbm9taWMgZmFjdG9ycywgcmVmbGVjdGluZyB0aGUgZGlzdGluY3RpdmUgY2hhcmFjdGVyaXN0aWNzIG9mIGVhY2ggY291bnR5IGFuZCB0aGUgbmVlZCBmb3IgdGFpbG9yZWQgbGFuZCBjb3ZlciBjaGFuZ2UgbW9kZWxpbmcgYXBwcm9hY2hlcy4NCg0KDQohW10oaW1hZ2VzL21vZGVsX2ltcG9ydGFuY2UucG5nKQ0KDQoNCiMjIDYuIFByZWRpY3Rpb24gJiBFcnJvciBBbmFseXNpcw0KDQpJbiB0aGlzIHNlY3Rpb24sIHdlIHByZXNlbnQgdGhlIHZpc3VhbGl6YXRpb25zIG9mIG91ciBtb2RlbCdzIHJlc3VsdHMsIGhpZ2hsaWdodGluZyBhcmVhcyB3aGVyZSBsYW5kIGNvdmVyIGNoYW5nZXMgZnJvbSBwZXJ2aW91cyB0byBpbXBlcnZpb3VzIHN1cmZhY2VzIGFyZSBtb3N0IGxpa2VseSB0byBvY2N1ci4gDQoNCkluIEphbWVzIENpdHkgQ291bnR5LCB0aGUgbW9kZWwgcHJlZGljdHMgbGFuZCBjb3ZlciBjaGFuZ2VzIGFyZSBtb3JlIGxpa2VseSB0byBoYXBwZW4gaW4gYXJlYXMgd2l0aCBzdGVlcGVyIHNsb3BlcyBhbmQgaW4gY2xvc2UgcHJveGltaXR5IHRvIGV4aXN0aW5nIGRldmVsb3BtZW50LCBwYXJ0aWN1bGFybHkgaW4gdGhlIG5vcnRoZXJuIGFuZCBzb3V0aGVhc3Rlcm4gcGFydHMgb2YgdGhlIGNvdW50eS4NCg0KSW4gUG9ydHNtb3V0aCBDb3VudHksIHRoZSBjb252ZXJzaW9uIGZyb20gcGVydmlvdXMgdG8gaW1wZXJ2aW91cyBzdXJmYWNlcyBpcyBwcmVkaWN0ZWQgdG8gYmUgbW9yZSBsaWtlbHkgaW4gdHdvIHdhdGVyZnJvbnQgYXJlYXMgbG9jYXRlZCBpbiB0aGUgZWFzdGVybiBwYXJ0IG9mIHRoZSBjb3VudHkgYW5kIGluIHRoZSBtaWR0b3duIHJlZ2lvbi4NCg0KSW4gSXNsZSBvZiBXaWdodCBDb3VudHksIGxhbmQgY292ZXIgY2hhbmdlcyBmcm9tIHBlcnZpb3VzIHRvIGltcGVydmlvdXMgc3VyZmFjZXMgYXBwZWFyIHRvIGJlIG1vcmUgc2NhdHRlcmVkIHRocm91Z2hvdXQgdGhlIHJlZ2lvbiwgcmVmbGVjdGluZyBhIG1vcmUgZGl2ZXJzZSBwYXR0ZXJuIG9mIHBvdGVudGlhbCBkZXZlbG9wbWVudC4NCg0KIVtdKGltYWdlcy9yaXNrLnBuZykNCg0KQnkgY29tcGFyaW5nIHRoZSBwcmVkaWN0ZWQgMjAxOCBsYW5kIGNvdmVyIGNoYW5nZSB3aXRoIHRoZSBvYnNlcnZlZCBjaGFuZ2UsIHdlIGNhbiB0ZWxsIHRoYXQgZXJyb3JzIGluIHRoZSBwcmVkaWN0aW9uIGFyZSBsaWtlbHkgdG8gYmUgYXJvdW5kIHRoZSB0cnVlIHZhbHVlLCBpbmRpY2F0aW5nIHRoZSBlZmZlY3RpdmVuZXNzIG9mIHRoZSBtb2RlbC4gTG9va2luZyBhdCB0aGUgZnV0dXJlIHByZWRpY3Rpb24gb2YgMjAyMSwgd2UgY2FuIHNlZSB0aGF0IG1hbnkgb2YgdGhlIHByZWRpY3RlZCBjaGFuZ2VzIGFyZSBjb25zaXN0ZW50IHdpdGggdGhlIG9ic2VydmVkIGNoYW5nZS4gSG93ZXZlciwgdGhlIG1vZGVsIGhhcyBhbHNvIGlkZW50aWZpZWQgbmV3IGFyZWFzIG9mIGxhbmQgY292ZXIgY2hhbmdlLiBUaGlzIHN1Z2dlc3RzIHRoYXQgdGhlIG1vZGVsIGlzIGFibGUgdG8gZGV0ZWN0IGNoYW5nZXMgdGhhdCB3ZXJlIG5vdCBwcmV2aW91c2x5IG9ic2VydmVkLCB3aGljaCBjYW4gYmUgdmFsdWFibGUgZm9yIGxhbmQgbWFuYWdlbWVudCBhbmQgY29uc2VydmF0aW9uIGVmZm9ydHMuDQoNCg0KIVtdKGltYWdlcy9wcmVkaWN0LnBuZykNCg0KDQohW10oaW1hZ2VzL3ByZWRpYzEwMDAucG5nKQ0KDQoNCg0KIyMgNy4gQ29uY2x1c2lvbg0KSW4gY29uY2x1c2lvbiwgd2Ugc3VjY2Vzc2Z1bGx5IGRlc2lnbmVkIGFuZCBzZXQgdXAgYW4gZWZmaWNpZW50IHdvcmtmbG93IGZvciB0ZXN0aW5nIGFuZCBtb2RlbGluZyBsYW5kIGNvdmVyIGNoYW5nZSBwcmVkaWN0aW9ucy4gT3VyIGNob3NlbiBtb2RlbCwgUmFuZG9tIEZvcmVzdCwgYWNoaWV2ZWQgYSBoaWdoIGJhbGFuY2VkIGFjY3VyYWN5IG9mIGFwcHJveGltYXRlbHkgOTglLCB3aXRoIHBlcmZvcm1hbmNlIG1ldHJpY3MgaW5kaWNhdGluZyB0aGF0IGl0IGdlbmVyYWxpemVzIHdlbGwgYWNyb3NzIGRpZmZlcmVudCBjb3VudGllcyBhbmQgbGFuZCBjb3ZlciB0eXBlcy4gSG93ZXZlciwgdGhlIG1vZGVsIHNjcmlwdHMgcmVxdWlyZSBhIGNvbnNpZGVyYWJsZSBhbW91bnQgb2YgdGltZSB0byBydW4sIHdoaWNoIG1pZ2h0IHBvc2UgY2hhbGxlbmdlcyBmb3IgcmVwbGljYXRpb24gYW5kIHNjYWxhYmlsaXR5Lg0KDQpBZGRpdGlvbmFsbHksIHRoZSBtb2RlbCBkZW1vbnN0cmF0ZXMgbG93ZXIgYWNjdXJhY3kgaW4gcHJlZGljdGluZyBsYW5kIGNvdmVyIGNoYW5nZSBjb21wYXJlZCB0byBubyBjaGFuZ2UsIHdoaWNoIGNhbiBiZSBhdHRyaWJ1dGVkIHRvIHRoZSB1bmV2ZW4gZGlzdHJpYnV0aW9uIG9mIGRhdGEuIERlc3BpdGUgdGhlc2UgbGltaXRhdGlvbnMsIHdlIGFyZSBjb25maWRlbnQgdGhhdCBvdXIgbW9kZWwgYW5kIGFjY29tcGFueWluZyBhcHAgY2FuIHNpZ25pZmljYW50bHkgY29udHJpYnV0ZSB0byB0aGUgdXRpbGl0eSBvZiBwcmVjaXNpb24gY29uc2VydmF0aW9uIGluIGxhbmQgcHJvdGVjdGlvbiBhbmQgZ3JlZW4gaW5mcmFzdHJ1Y3R1cmUgcGxhbm5pbmcuIFVsdGltYXRlbHksIG91ciBwcm9qZWN0IHByb3ZpZGVzIGEgdmFsdWFibGUgdG9vbCBmb3IgcGxhbm5lcnMgYW5kIHBvbGljeW1ha2VycyBhY3Jvc3MgdGhlIHJlZ2lvbiwgZW5hYmxpbmcgdGhlbSB0byBtYWtlIGluZm9ybWVkIGRlY2lzaW9ucyBvbiBsYW5kIHVzZSBtYW5hZ2VtZW50IGFuZCBjb25zZXJ2YXRpb24gc3RyYXRlZ2llcy4NCg0KIyMgOC4gQ29kZSBBcHBlbmRpeA0KDQpgYGB7ciBldmFsPUZBTFNFfQ0KDQojIyMjIyMjIyMjIyBSZXF1aXJlZCBQYWNrYWdlcyAjIyMjIyMjIyMjIw0KcGFja2FnZXMgPSBjKCJzdGFycyIsInN0YXJzRXh0cmEiLCAiYWJpbmQiLCJ0aWdyaXMiLCJ0aWR5Y2Vuc3VzIiwiZHlwbHlyIiwNCiAgICAgICAgICAgICAiYmF5ZXNwbG90IiwgImxtZTQiLCJSY3BwRWlnZW4iLCJrbml0ciIsInlhcmRzdGljayIsDQogICAgICAgICAgICAgInRpZHl2ZXJzZSIsICJ0aWR5ciIsICJicm9vbSIsICJjYXJldCIsICJkaWFscyIsICJkb1BhcmFsbGVsIiwgImUxMDcxIiwgImVhcnRoIiwNCiAgICAgICAgICAgICAiZ2dyZXBlbCIsICJnbG1uZXQiLCAiaXByZWQiLCAia2xhUiIsICJra25uIiwgInBST0MiLCAicnBhcnQiLCAicmFuZG9tRm9yZXN0IiwNCiAgICAgICAgICAgICAic2Vzc2lvbmluZm8iLCAidGlkeW1vZGVscyIsInJhbmdlciIsICJyZWNpcGVzIiwgIndvcmtmbG93cyIsICJ0aGVtaXMiLCJ4Z2Jvb3N0IiwNCiAgICAgICAgICAgICAic2YiLCAibm5nZW8iLCAibWFwdmlldyIsInJhc3RlciIpDQoNCg0KIyMjIyMjIyMjIyMgRGVmaW5lIEZ1bmN0aW9ucyAjIyMjIyMjIyMjIw0KDQpMb2FkLmZ1biA8LSBmdW5jdGlvbih4KSB7IA0KICB4IDwtIGFzLmNoYXJhY3Rlcih4KSANCiAgaWYoaXNUUlVFKHggJWluJSAucGFja2FnZXMoYWxsLmF2YWlsYWJsZT1UUlVFKSkpIHsgDQogICAgZXZhbChwYXJzZSh0ZXh0PXBhc3RlKCJyZXF1aXJlKCIsIHgsICIpIiwgc2VwPSIiKSkpIA0KICAgIHByaW50KHBhc3RlKGMoeCwgIiA6IGFscmVhZHkgaW5zdGFsbGVkOyByZXF1aXJpbmciKSwgY29sbGFwc2U9JycpKQ0KICB9IGVsc2UgeyANCiAgICAjdXBkYXRlLnBhY2thZ2VzKCkNCiAgICBwcmludChwYXN0ZShjKHgsICIgOiBub3QgaW5zdGFsbGVkOyBpbnN0YWxsaW5nIiksIGNvbGxhcHNlPScnKSkNCiAgICBldmFsKHBhcnNlKHRleHQ9cGFzdGUoImluc3RhbGwucGFja2FnZXMoJyIsIHgsICInKSIsIHNlcD0iIikpKSANCiAgICBwcmludChwYXN0ZShjKHgsICIgOiBpbnN0YWxsZWQgYW5kIHJlcXVpcmluZyIpLCBjb2xsYXBzZT0nJykpDQogICAgZXZhbChwYXJzZSh0ZXh0PXBhc3RlKCJyZXF1aXJlKCIsIHgsICIpIiwgc2VwPSIiKSkpIA0KICB9IA0KfSANCg0KZm9yKGkgaW4gc2VxX2Fsb25nKHBhY2thZ2VzKSl7DQogIHBhY2tnZSA8LSBhcy5jaGFyYWN0ZXIocGFja2FnZXNbaV0pDQogIExvYWQuZnVuKHBhY2tnZSkNCn0NCg0KcGxvdFRoZW1lIDwtIGZ1bmN0aW9uKGJhc2Vfc2l6ZSA9IDEyLCB0aXRsZV9zaXplID0gMTIpIHsNCiAgdGhlbWUoDQogICB0ZXh0ID0gZWxlbWVudF90ZXh0KCBjb2xvciA9ICJibGFjayIpLA0KICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gdGl0bGVfc2l6ZSwgY29sb3VyID0gImJsYWNrIiksIA0KICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2U9Iml0YWxpYyIpLA0KICAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChoanVzdD0wKSwNCiAgICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfbGluZSgiZ3JleTkwIiwgc2l6ZSA9IDAuMDEpLA0KICAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZSgiZ3JleTkwIiwgc2l6ZSA9IDAuMDEpLA0KICAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG91ciA9ICJ3aGl0ZSIgLCBmaWxsPU5BLCBzaXplPTApLA0KICAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJ3aGl0ZSIsZmlsbD0nd2hpdGUnKSwNCiAgICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xMiksDQogICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTIpLA0KICAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLA0KICAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3VyID0gImJsYWNrIiwgZmFjZSA9ICJpdGFsaWMiKSwNCiAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJibGFjayIsIGZhY2UgPSAiaXRhbGljIiksDQogICAgICAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpDQogICAgICAgKQ0KICAgfQ0KbWFwVGhlbWUgPC0gdGhlbWUocGxvdC50aXRsZSA9ZWxlbWVudF90ZXh0KHNpemU9MTIpLA0KICAgICAgICAgICAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTgpLA0KICAgICAgICAgICAgICAgICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KHNpemUgPSA2KSwNCiAgICAgICAgICAgICAgICAgIGF4aXMubGluZT1lbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgICBheGlzLnRpY2tzPWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnk9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgICAgICAgICAgcGFuZWwuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgICBwYW5lbC5ib3JkZXI9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgICAgICAgICAgcGFuZWwuZ3JpZC5tYWpvcj1lbGVtZW50X2xpbmUoY29sb3VyID0gJ3RyYW5zcGFyZW50JyksDQogICAgICAgICAgICAgICAgICBwYW5lbC5ncmlkLm1pbm9yPWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgICAgICAgICAgIGxlZ2VuZC5kaXJlY3Rpb24gPSAidmVydGljYWwiLCANCiAgICAgICAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsDQogICAgICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigxLCAxLCAxLCAxLCAnY20nKSwNCiAgICAgICAgICAgICAgICAgIGxlZ2VuZC5rZXkuaGVpZ2h0ID0gdW5pdCgxLCAiY20iKSwgbGVnZW5kLmtleS53aWR0aCA9IHVuaXQoMC4yLCAiY20iKSkNCg0KcGFsZXR0ZTIgPC0gYygiIzQxYjZjNCIsIiMyNTM0OTQiKQ0KcGFsZXR0ZTQgPC0gYygiI2ExZGFiNCIsIiM0MWI2YzQiLCIjMmM3ZmI4IiwiIzI1MzQ5NCIpDQpwYWxldHRlNSA8LSBjKCIjZmZmZmNjIiwiI2ExZGFiNCIsIiM0MWI2YzQiLCIjMmM3ZmI4IiwiIzI1MzQ5NCIpDQpwYWxldHRlMTAgPC0gYygiI2Y3ZmNmMCIsIiNlMGYzZGIiLCIjY2NlYmM1IiwiI2E4ZGRiNSIsIiM3YmNjYzQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgIiM0ZWIzZDMiLCIjMmI4Y2JlIiwiIzA4NjhhYyIsIiMwODQwODEiLCIjZjdmY2YwIikNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyAgLS0tLS0tLS0tLS0tLS0tLS0tLS0gICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgfCAgICAgICAgICAgICAgICAgICAgfCAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIHwgIERBVEEgUFJFUEFSQVRJT04gIHwgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyB8ICAgICAgICAgICAgICAgICAgICB8ICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgIC0tLS0tLS0tLS0tLS0tLS0tLS0tICAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KIyBsb2FkIGFsbCB0aGUgbGFuZCBjb3ZlciBkYXRhDQpwb3J0XzE0IDwtIHJlYWRfc3RhcnMoIn4vR2l0aHViL1ByZWNpc2lvbi1Gb3JlY2FzdHMtb2YtTGFuZC1Db3Zlci1DaGFuZ2UvRGF0YS9sYy9wb3J0XzUxNzQwX2xjXzIwMTQvcG9ydF81MTc0MF9sYW5kY292ZXJfMjAxNC50aWYiKSANCnBvcnRfMTggPC0gcmVhZF9zdGFycygifi9HaXRodWIvUHJlY2lzaW9uLUZvcmVjYXN0cy1vZi1MYW5kLUNvdmVyLUNoYW5nZS9EYXRhL2xjL3BvcnRfNTE3NDBfbGNfMjAxOC9wb3J0XzUxNzQwX2xhbmRjb3Zlcl8yMDE4LnRpZiIpDQpqYW1lc18xNCA8LSByZWFkX3N0YXJzKCJ+L0dpdGh1Yi9QcmVjaXNpb24tRm9yZWNhc3RzLW9mLUxhbmQtQ292ZXItQ2hhbmdlL0RhdGEvbGMvamFtZV81MTA5NV9sY18yMDE0L2phbWVfNTEwOTVfbGFuZGNvdmVyXzIwMTQudGlmIikNCmphbWVzXzE4IDwtIHJlYWRfc3RhcnMoIn4vR2l0aHViL1ByZWNpc2lvbi1Gb3JlY2FzdHMtb2YtTGFuZC1Db3Zlci1DaGFuZ2UvRGF0YS9sYy9qYW1lXzUxMDk1X2xjXzIwMTgvamFtZV81MTA5NV9sYW5kY292ZXJfMjAxOC50aWYiKQ0KDQppc2xlXzE0XzEwIDwtIHJlYWRfc3RhcnMoIn4vR2l0aHViL1ByZWNpc2lvbi1Gb3JlY2FzdHMtb2YtTGFuZC1Db3Zlci1DaGFuZ2UvRGF0YS9sYy9pc2xlbGNfMTRfMTB4MTAudGlmIikNCmlzbGVfMThfMTAgPC0gcmVhZF9zdGFycygifi9HaXRodWIvUHJlY2lzaW9uLUZvcmVjYXN0cy1vZi1MYW5kLUNvdmVyLUNoYW5nZS9EYXRhL2xjL2lzbGVsY18xOF8xMHgxMC50aWYiKQ0KDQojIGxvYWQgYWxsIHRoZSBib3VuZGFyeSBkYXRhIA0KcG9ydF9hcmVhIDwtIHN0X3JlYWQoIn4vR2l0aHViL1ByZWNpc2lvbi1Gb3JlY2FzdHMtb2YtTGFuZC1Db3Zlci1DaGFuZ2UvRGF0YS9ib3VuZGFyeS9wb3J0c21vdXRoLnNocCIpDQpqYW1lc19hcmVhIDwtIHN0X3JlYWQoIn4vR2l0aHViL1ByZWNpc2lvbi1Gb3JlY2FzdHMtb2YtTGFuZC1Db3Zlci1DaGFuZ2UvRGF0YS9ib3VuZGFyeS9KYW1lcy5zaHAiKQ0KaXNsZV9hcmVhIDwtIHN0X3JlYWQoIn4vR2l0aHViL1ByZWNpc2lvbi1Gb3JlY2FzdHMtb2YtTGFuZC1Db3Zlci1DaGFuZ2UvRGF0YS9ib3VuZGFyeS9Jc2xlX29mX1dpZ2h0LnNocCIpDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgIC0tLS0tLS0tLS0tLS0tLS0tLS0tICAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIHwgTEFORENPVkVSIERBVEFTRVQgIHwgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyAgLS0tLS0tLS0tLS0tLS0tLS0tLS0gICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQoNCiMgUmVzYW1wbGUgdGhlIHJhc3RlciBpbWFnZSB0byAxMHgxMCBjZWxscw0KcG9ydF8xNF8xMCA8LSBzdF93YXJwKHBvcnRfMTQsIGNlbGxzaXplID0gMTAsIGNycyA9IHN0X2Nycyhwb3J0XzE0KSkNCnBvcnRfMThfMTAgPC0gc3Rfd2FycChwb3J0XzE4LCBjZWxsc2l6ZSA9IDEwLCBjcnMgPSBzdF9jcnMocG9ydF8xOCkpDQpqYW1lXzE0XzEwIDwtIHN0X3dhcnAoamFtZV8xNCwgY2VsbHNpemUgPSAxMCwgY3JzID0gc3RfY3JzKGphbWVfMTQpKQ0KamFtZV8xOF8xMCA8LSBzdF93YXJwKGphbWVfMTgsIGNlbGxzaXplID0gMTAsIGNycyA9IHN0X2NycyhqYW1lXzE4KSkNCg0KcG9ydF9hcmVhIDwtIHBvcnRfYXJlYSAlPiUgDQogIHN0X3RyYW5zZm9ybShjcnMgPSBzdF9jcnMocG9ydF8xNCkpDQpqYW1lX2FyZWEgPC0gamFtZV9hcmVhICU+JSANCiAgc3RfdHJhbnNmb3JtKGNycyA9IHN0X2NycyhqYW1lXzE0KSkNCmlzbGVfYXJlYSA8LSBpc2xlX2FyZWEgJT4lIA0KICBzdF90cmFuc2Zvcm0oY3JzID0gc3RfY3JzKGlzbGVfMTQpKQ0KDQojIENyb3AgdGhlIHJlc2FtcGxlZCByYXN0ZXIgaW1hZ2UgdG8gdGhlIHRlc3QgYXJlYQ0KcG9ydF8xNF8xMF9jcm9wIDwtIHN0X2Nyb3AocG9ydF8xNF8xMCwgcG9ydF9hcmVhKQ0KcG9ydF8xOF8xMF9jcm9wIDwtIHN0X2Nyb3AocG9ydF8xOF8xMCwgcG9ydF9hcmVhKQ0KamFtZV8xNF8xMF9jcm9wIDwtIHN0X2Nyb3AoamFtZV8xNF8xMCwgamFtZV9hcmVhKQ0KamFtZV8xOF8xMF9jcm9wIDwtIHN0X2Nyb3AoamFtZV8xOF8xMCwgamFtZV9hcmVhKQ0KaXNsZV8xNF8xMF9jcm9wIDwtIHN0X2Nyb3AoaXNsZV8xNCwgaXNsZV9hcmVhKQ0KaXNsZV8xOF8xMF9jcm9wIDwtIHN0X2Nyb3AoaXNsZV8xOCwgaXNsZV9hcmVhKQ0KDQoNCiMgQ3JlYXRlIGxhbmQgY292ZXIgY2hhbmdlIGZlYXR1cmUNCnBvcnRfY2hhbmdlIDwtIGMocG9ydF8xOF8xMF9jcm9wIC0gcG9ydF8xNF8xMF9jcm9wKSU+JQ0KICBtdXRhdGUobGNjaGFuZ2UgPSBjYXNlX3doZW4ocG9ydF81MTc0MF9sYW5kY292ZXJfMjAxOC50aWYgIT0gMCB+IDEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3J0XzUxNzQwX2xhbmRjb3Zlcl8yMDE4LnRpZiAhPSAwIH4gMCkpDQpqYW1lX2NoYW5nZSA8LSBjKGphbWVfMThfMTBfY3JvcCAtIGphbWVfMTRfMTBfY3JvcCklPiUNCiAgbXV0YXRlKGxjY2hhbmdlID0gY2FzZV93aGVuKGphbWVfNTEwOTVfbGFuZGNvdmVyXzIwMTgudGlmICE9IDAgfiAxLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgamFtZV81MTA5NV9sYW5kY292ZXJfMjAxNC50aWYhPSAwIH4gMCkpDQppc2xlX2NoYW5nZSA8LSBjKGlzbGVfMThfMTBfY3JvcCAtIGlzbGVfMTRfMTBfY3JvcCklPiUNCiAgbXV0YXRlKGxjY2hhbmdlID0gY2FzZV93aGVuKGlzbGVsY18xOF8xMHgxMC50aWYgIT0gMCB+IDEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc2xlbGNfMThfMTB4MTAudGlmICE9IDAgfiAwKSkNCg0KIyBSZWNsYXNzaWZ5IHRoZSBjcm9wcGVkIHJhc3RlciBpbWFnZQ0KcG9ydF8xNF8xMF9yYyA8LSBwb3J0XzE0XzEwX2Nyb3AgJT4lIA0KICBtdXRhdGUoDQogICAgb3JpZ2luYWxsYyA9ICBwb3J0XzUxNzQwX2xhbmRjb3Zlcl8yMDE0LnRpZiwNCiAgICBsYyA9IGNhc2Vfd2hlbigNCiAgICBwb3J0XzUxNzQwX2xhbmRjb3Zlcl8yMDE0LnRpZiA8IDYgIH4gMCwgIyBwcmV2aW91cw0KICAgIHBvcnRfNTE3NDBfbGFuZGNvdmVyXzIwMTQudGlmID49IDYgfiAxICMgaW1wZXJ2aW91cw0KICApKQ0KcG9ydF8xOF8xMF9yYyA8LSBwb3J0XzE4XzEwX2Nyb3AgJT4lIA0KICBtdXRhdGUoDQogICAgb3JpZ2luYWxsYyA9ICBwb3J0XzUxNzQwX2xhbmRjb3Zlcl8yMDE4LnRpZiwNCiAgICBsYyA9IGNhc2Vfd2hlbigNCiAgICBwb3J0XzUxNzQwX2xhbmRjb3Zlcl8yMDE4LnRpZiA8IDYgIH4gMCwNCiAgICBwb3J0XzUxNzQwX2xhbmRjb3Zlcl8yMDE4LnRpZiA+PSA2IH4gMQ0KICApKQ0KamFtZV8xNF8xMF9yYyA8LSBqYW1lXzE0XzEwX2Nyb3AgJT4lIA0KICBtdXRhdGUob3JpZ2luYWxsYyA9IGphbWVfNTEwOTVfbGFuZGNvdmVyXzIwMTQudGlmLA0KICAgICAgICAgbGMgPSBjYXNlX3doZW4oDQogICAgICAgICBqYW1lXzUxMDk1X2xhbmRjb3Zlcl8yMDE0LnRpZiA8IDYgIH4gMCwgIyBwZXJtZWFibGUNCiAgICAgICAgIGphbWVfNTEwOTVfbGFuZGNvdmVyXzIwMTQudGlmID49IDYgfiAxICMgaW1wZXJtZWFibGUNCiAgICAgICAgICkpDQpqYW1lXzE4XzEwX3JjIDwtIGphbWVfMThfMTBfY3JvcCAlPiUgDQogIG11dGF0ZShvcmlnaW5hbGxjID0gamFtZV81MTA5NV9sYW5kY292ZXJfMjAxOC50aWYsDQogICAgICAgICBsYyA9IGNhc2Vfd2hlbigNCiAgICAgICAgICAgamFtZV81MTA5NV9sYW5kY292ZXJfMjAxOC50aWYgPCA2ICB+IDAsDQogICAgICAgICAgIGphbWVfNTEwOTVfbGFuZGNvdmVyXzIwMTgudGlmID49IDYgfiAxDQogICAgICAgICApKQ0KDQppc2xlXzE0XzEwX3JjIDwtIGlzbGVfMTRfMTBfY3JvcCAlPiUgDQogIG11dGF0ZShvcmlnaW5hbGxjID0gY2FzZV93aGVuKA0KICAgIGlzbGVsY18xNF8xMHgxMC50aWYgPT0gMSAgfiAxLA0KICAgIGlzbGVsY18xNF8xMHgxMC50aWYgPT0gMiB+IDIsDQogICAgaXNsZWxjXzE0XzEweDEwLnRpZiA9PSAzIH4gMywNCiAgICBpc2xlbGNfMTRfMTB4MTAudGlmID09IDQgfiA0LA0KICAgIGlzbGVsY18xNF8xMHgxMC50aWYgPT0gNSB+IDUsDQogICAgaXNsZWxjXzE0XzEweDEwLnRpZiA9PSA2IH4gNiwNCiAgICBpc2xlbGNfMTRfMTB4MTAudGlmID09IDcgfiA3LA0KICAgIGlzbGVsY18xNF8xMHgxMC50aWYgPT0gOCB+IDgsDQogICAgaXNsZWxjXzE0XzEweDEwLnRpZiA9PSA5IH4gOSwNCiAgICBpc2xlbGNfMTRfMTB4MTAudGlmID09IDEwIH4gMTAsDQogICAgaXNsZWxjXzE0XzEweDEwLnRpZiA9PSAxMSAgfiAxMSwNCiAgICBpc2xlbGNfMTRfMTB4MTAudGlmID09IDEyIH4gMTINCiAgKSwNCiAgbGMgPSBjYXNlX3doZW4oDQogICAgaXNsZWxjXzE0XzEweDEwLnRpZiA8IDYgIH4gMCwgIyBwZXJtZWFibGUNCiAgICBpc2xlbGNfMTRfMTB4MTAudGlmID49IDYgfiAxICMgaW1wZXJtZWFibGUNCiAgKSkNCmlzbGVfMThfMTBfcmMgPC0gaXNsZV8xOF8xMF9jcm9wICU+JSANCiAgbXV0YXRlKA0KICAgIG9yaWdpbmFsbGMgPWNhc2Vfd2hlbigNCiAgICAgIGlzbGVsY18xOF8xMHgxMC50aWYgPT0gMSAgfiAxLA0KICAgICAgaXNsZWxjXzE4XzEweDEwLnRpZiA9PSAyIH4gMiwNCiAgICAgIGlzbGVsY18xOF8xMHgxMC50aWYgPT0gMyB+IDMsDQogICAgICBpc2xlbGNfMThfMTB4MTAudGlmID09IDQgfiA0LA0KICAgICAgaXNsZWxjXzE4XzEweDEwLnRpZiA9PSA1IH4gNSwNCiAgICAgIGlzbGVsY18xOF8xMHgxMC50aWYgPT0gNiB+IDYsDQogICAgICBpc2xlbGNfMThfMTB4MTAudGlmID09IDcgfiA3LA0KICAgICAgaXNsZWxjXzE4XzEweDEwLnRpZiA9PSA4IH4gOCwNCiAgICAgIGlzbGVsY18xOF8xMHgxMC50aWYgPT0gOSB+IDksDQogICAgICBpc2xlbGNfMThfMTB4MTAudGlmID09IDEwIH4gMTAsDQogICAgICBpc2xlbGNfMThfMTB4MTAudGlmID09IDExICB+IDExLA0KICAgICAgaXNsZWxjXzE4XzEweDEwLnRpZiA9PSAxMiB+IDEyDQogICAgKSwNCiAgICBsYyA9IGNhc2Vfd2hlbigNCiAgICAgIGlzbGVsY18xOF8xMHgxMC50aWYgPCA2ICB+IDAsDQogICAgICBpc2xlbGNfMThfMTB4MTAudGlmID49IDYgfiAxDQogICAgKSkNCiMgQ3JlYXRlIHJlY2xhc3NlZCBsYW5kIGNvdmVyIGNoYW5nZSBmZWF0dXJlDQpwb3J0X2NoYW5nZV9yYyA8LSAocG9ydF8xOF8xMF9yYyAtIHBvcnRfMTRfMTBfcmMpDQpqYW1lX2NoYW5nZV9yYyA8LSAoamFtZV8xOF8xMF9yYyAtIGphbWVfMTRfMTBfcmMpDQppc2xlX2NoYW5nZV9yYyA8LSAoaXNsZV8xOF8xMF9yYyAtIGlzbGVfMTRfMTBfcmMpDQoNCiNyZW1vdmUNCnJtKHBvcnRfMTRfMTAscG9ydF8xOF8xMCxwb3J0XzE0LHBvcnRfMTgpDQpybShqYW1lXzE0XzEwLGphbWVfMThfMTAsamFtZV8xNCxqYW1lXzE4KQ0Kcm0oaXNsZV8xNF8xMCxpc2xlXzE4XzEwLGlzbGVfMTQsaXNsZV8xOCkNCg0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgIC0tLS0tLS0tLS0tLS0tLS0tLS0tICAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIHwgIENFTlNDVVMgREFUQVNFVCAgIHwgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyAgLS0tLS0tLS0tLS0tLS0tLS0tLS0gICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQoNCiMjIGxvYWQgY2Vuc3VzDQoNCm9wdGlvbnModGlncmlzX3VzZV9jYWNoZSA9IFRSVUUpDQoNCmNlbnN1c19hcGlfa2V5KCJiZDRjZTIwNTYxMTI1YTg0ODA2MzJkYjZhY2IyOTg2OWUwNDBlZDA4IixpbnN0YWxsID0gVFJVRSkNCg0KIyBEZWZpbmUgZnVuY3Rpb24gdG8gcmV0cmlldmUgY2Vuc3VzIGRhdGEgZm9yIGEgZ2l2ZW4gY291bnR5IGFuZCB5ZWFyDQpnZXRfY291bnR5X2RhdGEgPC0gZnVuY3Rpb24oc3RhdGUsIGNvdW50eSwgeWVhcikgew0KICBnZXRfYWNzKA0KICAgIGdlb2dyYXBoeSA9ICJibG9jayBncm91cCIsDQogICAgdmFyaWFibGVzID0gYygiQjAxMDAzXzAwMUUiLCJCMDIwMDFfMDAyRSIsIkIxOTAxM18wMDFFIiwiQjI1MDAyXzAwMUUiLCJCMDYwMTJfMDAyRSIsIkIyNzAxMV8wMDhFIiksDQogICAgeWVhciA9IHllYXIsDQogICAgc3RhdGUgPSBzdGF0ZSwNCiAgICBjb3VudHkgPSBjb3VudHksDQogICAgZ2VvbWV0cnkgPSBUUlVFLA0KICAgIG91dHB1dCA9ICJ3aWRlIg0KICApICU+JQ0KICAgIHN0X3RyYW5zZm9ybShzdF9jcnMocG9ydF8xOCkpICU+JQ0KICAgIHJlbmFtZSgNCiAgICAgIFRvdGFsUG9wID0gQjAxMDAzXzAwMUUsDQogICAgICBXaGl0ZXMgPSBCMDIwMDFfMDAyRSwNCiAgICAgIE1lZEhISW5jID0gQjE5MDEzXzAwMUUsDQogICAgICBUb3RhbFVuaXQgPSBCMjUwMDJfMDAxRQ0KICAgICkgJT4lDQogICAgbXV0YXRlKA0KICAgICAgcGN0V2hpdGUgPSBpZmVsc2UoVG90YWxQb3AgPiAwLCBXaGl0ZXMgLyBUb3RhbFBvcCAqIDEwMCwgMCksDQogICAgICBhcmVhID0gc3RfYXJlYShnZW9tZXRyeSkNCiAgICApICU+JQ0KICAgIGRwbHlyOjpzZWxlY3QoLU5BTUUsIC1zdGFydHNfd2l0aCgiQiIpLC1XaGl0ZXMpJT4lDQogICAgZmlsbChldmVyeXRoaW5nKCkpDQp9DQoNCiMgRGVmaW5lIGZ1bmN0aW9uIHRvIGNhbGN1bGF0ZSBjaGFuZ2VzIGluIGNlbnN1cyB2YXJpYWJsZXMgYmV0d2VlbiB0d28geWVhcnMNCmNhbGN1bGF0ZV9jaGFuZ2VzIDwtIGZ1bmN0aW9uKGRhdGExLCBkYXRhMikgew0KICBkYXRhMiAlPiUNCiAgICBzdF9qb2luKGRhdGExLGxlZnQgPSBUUlVFKSAlPiUNCiAgICBtdXRhdGUoDQogICAgICBwb3BjaGFuZ2UgPSAoVG90YWxQb3AueSAtIFRvdGFsUG9wLngpIC8gKFRvdGFsUG9wLnggKiBhcmVhLngpLA0KICAgICAgcGN0d2hpdGVjaGFuZ2UgPSAocGN0V2hpdGUueSAtIHBjdFdoaXRlLngpLA0KICAgICAgVW5pdGNoYW5nZSA9IChUb3RhbFVuaXQueSAtIFRvdGFsVW5pdC54KSAvIGFyZWEueCwNCiAgICAgIE1lZEhISW5jY2hhbmdlID0gKE1lZEhISW5jLnkgLSBNZWRISEluYy54KSAvIGFyZWEueCwNCiAgICAgIEFyZWEgPSBhcmVhLngsDQogICAgICBHRU9JRCA9IEdFT0lELngNCiAgICApJT4lDQogICAgZHBseXI6OnNlbGVjdCgtZW5kc193aXRoKCIueCIpLC1lbmRzX3dpdGgoIi55IikpDQp9DQoNCiMgUmV0cmlldmUgY2Vuc3VzIGRhdGEgZm9yIFBvcnRzbW91dGggaW4gMjAxNCBhbmQgDQpwb3J0c21vdXRoXzE0IDwtIGdldF9jb3VudHlfZGF0YShzdGF0ZSA9ICI1MSIsIGNvdW50eSA9ICJQb3J0c21vdXRoIiwgeWVhciA9IDIwMTQpDQpwb3J0c21vdXRoXzE4IDwtIGdldF9jb3VudHlfZGF0YShzdGF0ZSA9ICI1MSIsIGNvdW50eSA9ICJQb3J0c21vdXRoIiwgeWVhciA9IDIwMTgpDQpwb3J0c21vdXRoXzIxIDwtIGdldF9jb3VudHlfZGF0YShzdGF0ZSA9ICI1MSIsIGNvdW50eSA9ICJQb3J0c21vdXRoIiwgeWVhciA9IDIwMjEpDQojIENhbGN1bGF0ZSBjaGFuZ2VzIGluIGNlbnN1cyB2YXJpYWJsZXMgYmV0d2VlbiAyMDE0IGFuZCAyMDE4DQpwb3J0X3RyYWN0IDwtIGNhbGN1bGF0ZV9jaGFuZ2VzKGRhdGExID0gcG9ydHNtb3V0aF8xNCwgZGF0YTIgPSBwb3J0c21vdXRoXzE4KQ0KcG9ydF90cmFjdDIgPC0gY2FsY3VsYXRlX2NoYW5nZXMoZGF0YTEgPSBwb3J0c21vdXRoXzE4LCBkYXRhMiA9IHBvcnRzbW91dGhfMjEpDQoNCiMgUmVwZWF0IGZvciBKYW1lcyBDaXR5IGFuZCBJc2xlIG9mIFdpZ2h0IGNvdW50aWVzDQpqYW1lc19jaXR5XzE0IDwtIGdldF9jb3VudHlfZGF0YShzdGF0ZSA9ICI1MSIsIGNvdW50eSA9ICJKYW1lcyBDaXR5IiwgeWVhciA9IDIwMTQpDQpqYW1lc19jaXR5XzE4IDwtIGdldF9jb3VudHlfZGF0YShzdGF0ZSA9ICI1MSIsIGNvdW50eSA9ICJKYW1lcyBDaXR5IiwgeWVhciA9IDIwMTgpDQpqYW1lc19jaXR5XzIxIDwtIGdldF9jb3VudHlfZGF0YShzdGF0ZSA9ICI1MSIsIGNvdW50eSA9ICJKYW1lcyBDaXR5IiwgeWVhciA9IDIwMjEpDQpqYW1lX3RyYWN0IDwtIGNhbGN1bGF0ZV9jaGFuZ2VzKGRhdGExID0gamFtZXNfY2l0eV8xNCwgZGF0YTIgPSBqYW1lc19jaXR5XzE4KQ0KamFtZV90cmFjdDIgPC0gY2FsY3VsYXRlX2NoYW5nZXMoZGF0YTEgPSBqYW1lc19jaXR5XzE4LCBkYXRhMiA9IGphbWVzX2NpdHlfMjEpDQoNCmlzbGVfb2Zfd2lnaHRfMTQgPC0gZ2V0X2NvdW50eV9kYXRhKHN0YXRlID0gIjUxIiwgY291bnR5ID0gIklzbGUgb2YgV2lnaHQiLCB5ZWFyID0gMjAxNCkNCmlzbGVfb2Zfd2lnaHRfMTggPC0gZ2V0X2NvdW50eV9kYXRhKHN0YXRlID0gIjUxIiwgY291bnR5ID0gIklzbGUgb2YgV2lnaHQiLCB5ZWFyID0gMjAxOCkNCmlzbGVfb2Zfd2lnaHRfMjEgPC0gZ2V0X2NvdW50eV9kYXRhKHN0YXRlID0gIjUxIiwgY291bnR5ID0gIklzbGUgb2YgV2lnaHQiLCB5ZWFyID0gMjAyMSkNCmlzbGVfdHJhY3QgPC0gY2FsY3VsYXRlX2NoYW5nZXMoZGF0YTEgPSBpc2xlX29mX3dpZ2h0XzE0LCBkYXRhMiA9IGlzbGVfb2Zfd2lnaHRfMTgpDQppc2xlX3RyYWN0MiA8LSBjYWxjdWxhdGVfY2hhbmdlcyhkYXRhMSA9IGlzbGVfb2Zfd2lnaHRfMTgsIGRhdGEyID0gaXNsZV9vZl93aWdodF8yMSkNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyAgLS0tLS0tLS0tLS0tLS0tLS0tLS0gICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgfCAgICBERU0gREFUQVNFVCAgICAgfCAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjICAtLS0tLS0tLS0tLS0tLS0tLS0tLSAgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCg0KZGVtMSA8LSByZWFkX3N0YXJzKCJ+L0dpdGh1Yi9QcmVjaXNpb24tRm9yZWNhc3RzLW9mLUxhbmQtQ292ZXItQ2hhbmdlL0RhdGEvREVNL1VTR1NfMV9uMzh3MDc3XzIwMTcwNTA5LnRpZiIpDQpkZW0yIDwtIHJlYWRfc3RhcnMoIn4vR2l0aHViL1ByZWNpc2lvbi1Gb3JlY2FzdHMtb2YtTGFuZC1Db3Zlci1DaGFuZ2UvRGF0YS9ERU0vVVNHU18xX24zN3cwNzdfMjAxNjAzMTUudGlmIikNCmRlbSA8LSBzdF9tb3NhaWMoZGVtMSwgZGVtMikNCmRlbTIgPC0gc3Rfd2FycChkZW0yLCBjcnM9c3RfY3JzKHBvcnRfMTQpKQ0KZGVtX3BvcnQgPC0gc3RfY3JvcCAoZGVtMiwgcG9ydF9hcmVhKQ0KZGVtX3BvcnQgPC0gc3Rfd2FycChkZW1fcG9ydCwgcG9ydF8xNCkNCnBvcnRfc2xvcGU8LSBzbG9wZShkZW1fcG9ydCkNCg0KZGVtMSA8LSBzdF93YXJwKGRlbTEsIGNycz1zdF9jcnMoamFtZV9hcmVhKSkNCmRlbV9qYW1lcyA8LSBzdF9jcm9wIChkZW0xLCBqYW1lX2FyZWEpDQpkZW1famFtZXMgPC0gc3Rfd2FycChkZW1famFtZXMsIGphbWVfMThfMTBfY3JvcCkNCmphbWVzX3Nsb3BlPC0gc2xvcGUoZGVtX2phbWVzKQ0KDQpkZW0yIDwtIHN0X3dhcnAoZGVtLCBjcnM9c3RfY3JzKGlzbGVfMTRfMTBfcmMpKQ0KZGVtX2lzbGUgPC0gc3RfY3JvcCAoZGVtMiwgaXNsZV9hcmVhKQ0KZGVtX2lzbGUgPC0gc3Rfd2FycChkZW1faXNsZSwgaXNsZV8xNF8xMF9jcm9wKQ0KaXNsZV9zbG9wZTwtIHNsb3BlKGRlbV9pc2xlKQ0Kcm0oZGVtMSxkZW0yLGRlbSkNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyAgLS0tLS0tLS0tLS0tLS0tLS0tLS0gICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgfCAgICBTT0lMIERBVEFTRVQgICAgfCAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjICAtLS0tLS0tLS0tLS0tLS0tLS0tLSAgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCiMgUG9ydG1vdXRoDQpzb2lsIDwtIHN0X3JlYWQoJ34vR2l0aHViL1ByZWNpc2lvbi1Gb3JlY2FzdHMtb2YtTGFuZC1Db3Zlci1DaGFuZ2UvRGF0YS9Tb2lsL1BvcnQvcG9ydF9zb2lsLnNocCcsIGNycz0gJ0VQU0c6NDMyNicpDQpzb2lsY2xhc3MgPC0gc29pbCU+JQ0KICBtdXRhdGUoc29pbCA9IGNhc2Vfd2hlbigNCiAgICBQb3J0X19SYXRpID09ICdEJyB+IDYsDQogICAgUG9ydF9fUmF0aSA9PSAnQycgfiA1LA0KICAgIFBvcnRfX1JhdGkgPT0gJ0IvRCcgfiA0LA0KICAgIFBvcnRfX1JhdGkgPT0gJ0InIH4gMywNCiAgICBQb3J0X19SYXRpID09ICdBL0QnIH4gMiwNCiAgICBQb3J0X19SYXRpID09ICdBJyB+IDEsDQogICAgaXMubmEoUG9ydF9fUmF0aSkgfiAwDQogICkpICU+JQ0KICBkcGx5cjo6c2VsZWN0KC1jb2xuYW1lcyhzb2lsKSxnZW9tZXRyeSklPiUNCiAgc3RfdHJhbnNmb3JtKHN0X2Nycyhwb3J0XzE0XzEwX3JjKSkNCg0Kc29pbF9wb3J0IDwtIHN0X2Nyb3Aoc29pbGNsYXNzLCBwb3J0X2FyZWEpDQoNCiMgSmFtZXMgQ2l0eQ0Kc29pbCA8LSBzdF9yZWFkKCd+L0dpdGh1Yi9QcmVjaXNpb24tRm9yZWNhc3RzLW9mLUxhbmQtQ292ZXItQ2hhbmdlL0RhdGEvU29pbC9KYW1lcy9KYW1lc19zb2lsLnNocCcsIGNycz0gJ0VQU0c6NDMyNicpDQpzb2lsY2xhc3MgPC0gc29pbCU+JQ0KICBtdXRhdGUoc29pbCA9IGNhc2Vfd2hlbigNCiAgICBSZXBvcnRfX184ID09ICdEJyB+IDYsDQogICAgUmVwb3J0X19fOCA9PSAnQycgfiA1LA0KICAgIFJlcG9ydF9fXzggPT0gJ0IvRCcgfiA0LA0KICAgIFJlcG9ydF9fXzggPT0gJ0InIH4gMywNCiAgICBSZXBvcnRfX184ID09ICdBL0QnIH4gMiwNCiAgICBSZXBvcnRfX184ID09ICdBJyB+IDEsDQogICAgaXMubmEoUmVwb3J0X19fOCkgfiAwDQogICkpICU+JQ0KICBkcGx5cjo6c2VsZWN0KC1jb2xuYW1lcyhzb2lsKSxnZW9tZXRyeSklPiUNCiAgc3RfdHJhbnNmb3JtKHN0X2NycyhqYW1lXzE0XzEwX3JjKSkNCg0Kc29pbF9qYW1lIDwtIHN0X2Nyb3Aoc29pbGNsYXNzLCBqYW1lX2FyZWEpDQoNCiMgSXNsZSBvZiBXaWdodA0Kc29pbCA8LSBzdF9yZWFkKCd+L0dpdGh1Yi9QcmVjaXNpb24tRm9yZWNhc3RzLW9mLUxhbmQtQ292ZXItQ2hhbmdlL0RhdGEvU29pbC9pc2xlL2lzbGVfc29pbC5zaHAnLCBjcnM9ICdFUFNHOjQzMjYnKQ0Kc29pbGNsYXNzIDwtIHNvaWwlPiUNCiAgbXV0YXRlKHNvaWwgPSBjYXNlX3doZW4oDQogICAgaXNsZV9fUmFfMSA9PSAnRCcgfiA2LA0KICAgIGlzbGVfX1JhXzEgPT0gJ0MnIH4gNSwNCiAgICBpc2xlX19SYV8xID09ICdCL0QnIH4gNCwNCiAgICBpc2xlX19SYV8xID09ICdCJyB+IDMsDQogICAgaXNsZV9fUmFfMSA9PSAnQS9EJyB+IDIsDQogICAgaXNsZV9fUmFfMSA9PSAnQScgfiAxLA0KICAgIGlzLm5hKGlzbGVfX1JhXzEpIH4gMA0KICApKSAlPiUNCiAgZHBseXI6OnNlbGVjdCgtY29sbmFtZXMoc29pbCksZ2VvbWV0cnkpJT4lDQogIHN0X3RyYW5zZm9ybShzdF9jcnMoaXNsZV8xNF8xMF9yYykpDQoNCnNvaWxfaXNsZSA8LSBzdF9jcm9wKHNvaWxjbGFzcywgaXNsZV9hcmVhKQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyAgLS0tLS0tLS0tLS0tLS0tLS0tLS0gICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgfCBTUEFUSUFMIENBTENVTEFUSU9OIHwgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjICAtLS0tLS0tLS0tLS0tLS0tLS0tLSAgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCnBvcnRfMTRfcGNudF9pbXBlcnYgPSBmb2NhbDIocG9ydF8xNF8xMF9yY1sibGMiXSwgbWF0cml4KDEsIDMsIDMpLCAibWVhbiIpDQpwb3J0XzE4X3BjbnRfaW1wZXJ2ID0gZm9jYWwyKHBvcnRfMThfMTBfcmNbImxjIl0sIG1hdHJpeCgxLCAzLCAzKSwgIm1lYW4iKQ0KamFtZV8xNF9wY250X2ltcGVydiA9IGZvY2FsMihqYW1lXzE0XzEwX3JjWyJsYyJdLCBtYXRyaXgoMSwgMywgMyksICJtZWFuIikNCmphbWVfMThfcGNudF9pbXBlcnYgPSBmb2NhbDIoamFtZV8xOF8xMF9yY1sibGMiXSwgbWF0cml4KDEsIDMsIDMpLCAibWVhbiIpDQppc2xlXzE0X3BjbnRfaW1wZXJ2ID0gZm9jYWwyKGlzbGVfMTRfMTBfcmNbImxjIl0sIG1hdHJpeCgxLCAzLCAzKSwgIm1lYW4iKQ0KaXNsZV8xOF9wY250X2ltcGVydiA9IGZvY2FsMihpc2xlXzE4XzEwX3JjWyJsYyJdLCBtYXRyaXgoMSwgMywgMyksICJtZWFuIikNCg0KDQojIEZ1bmN0aW9uIHRvIGNhbGN1bGF0ZSBmb2NhbCBtZWFuDQpjYWxjX2ZvY2FsX21lYW4gPC0gZnVuY3Rpb24oZGYsIGZpZWxkLCBrc2l6ZSkgew0KICBmb2NhbDIoZGZbZmllbGRdLCBtYXRyaXgoMSwga3NpemUsIGtzaXplKSwgIm1lYW4iKSAlPiUNCiAgICBmb2NhbDIoLiwgbWF0cml4KDEsIGtzaXplLCBrc2l6ZSksICJtZWFuIikgJT4lDQogICAgZm9jYWwyKC4sIG1hdHJpeCgxLCBrc2l6ZSwga3NpemUpLCAibWVhbiIpDQp9DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyAgLS0tLS0tLS0tLS0tLS0tLS0tLS0gICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgfCAgICAgUE9SVE1PVVRIICAgICAgfCAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgIC0tLS0tLS0tLS0tLS0tLS0tLS0tICAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KDQojIFJvYWQNCnBvcnRfMTRfcm9hZCA8LSBwb3J0XzE0XzEwX2Nyb3AgJT4lDQogIG11dGF0ZShyb2FkID0gYXMubnVtZXJpYyhwb3J0XzUxNzQwX2xhbmRjb3Zlcl8yMDE0LnRpZiA9PSA5KSkNCg0KcG9ydF8xOF9yb2FkIDwtIHBvcnRfMThfMTBfY3JvcCAlPiUNCiAgbXV0YXRlKHJvYWQgPSBhcy5udW1lcmljKHBvcnRfNTE3NDBfbGFuZGNvdmVyXzIwMTgudGlmID09IDkpKQ0KDQpyb2FkXzE0IDwtIGNhbGNfZm9jYWxfbWVhbihwb3J0XzE0X3JvYWQsICJyb2FkIiwgMykNCnJvYWRfMTggPC0gY2FsY19mb2NhbF9tZWFuKHBvcnRfMThfcm9hZCwgInJvYWQiLCAzKQ0KDQojIENhbm9weQ0KcG9ydF8xNF9jYW5vcHkgPC0gcG9ydF8xNF8xMF9jcm9wICU+JQ0KICBtdXRhdGUoY2Fub3B5ID0gYXMubnVtZXJpYyhwb3J0XzUxNzQwX2xhbmRjb3Zlcl8yMDE0LnRpZiA9PSAzKSkNCg0KcG9ydF8xOF9jYW5vcHkgPC0gcG9ydF8xOF8xMF9jcm9wICU+JQ0KICBtdXRhdGUoY2Fub3B5ID0gYXMubnVtZXJpYyhwb3J0XzUxNzQwX2xhbmRjb3Zlcl8yMDE4LnRpZiA9PSAzKSkNCg0KY2Fub3B5XzE0X21lYW4gPC0gY2FsY19mb2NhbF9tZWFuKHBvcnRfMTRfY2Fub3B5LCAiY2Fub3B5IiwgMykNCmNhbm9weV8xOF9tZWFuIDwtIGNhbGNfZm9jYWxfbWVhbihwb3J0XzE4X2Nhbm9weSwgImNhbm9weSIsIDMpDQoNCiMgU2hydWINCnBvcnRfMTRfc2hydWIgPC0gcG9ydF8xNF8xMF9jcm9wICU+JQ0KICBtdXRhdGUoc2hydWIgPSBhcy5udW1lcmljKHBvcnRfNTE3NDBfbGFuZGNvdmVyXzIwMTQudGlmID09IDIpKQ0KDQpwb3J0XzE4X3NocnViIDwtIHBvcnRfMThfMTBfY3JvcCAlPiUNCiAgbXV0YXRlKHNocnViID0gYXMubnVtZXJpYyhwb3J0XzUxNzQwX2xhbmRjb3Zlcl8yMDE4LnRpZiA9PSAyKSkNCg0Kc2hydWJfMTRfbWVhbiA8LSBjYWxjX2ZvY2FsX21lYW4ocG9ydF8xNF9zaHJ1YiwgInNocnViIiwgMykNCnNocnViXzE4X21lYW4gPC0gY2FsY19mb2NhbF9tZWFuKHBvcnRfMThfc2hydWIsICJzaHJ1YiIsIDMpDQoNCiMgV2F0ZXINCnBvcnRfMTRfd2F0ZXIgPC0gcG9ydF8xNF8xMF9jcm9wICU+JQ0KICBtdXRhdGUod2F0ZXIgPSBhcy5udW1lcmljKHBvcnRfNTE3NDBfbGFuZGNvdmVyXzIwMTQudGlmID09IDEpKQ0KDQpwb3J0XzE4X3dhdGVyIDwtIHBvcnRfMThfMTBfY3JvcCAlPiUNCiAgbXV0YXRlKHdhdGVyID0gYXMubnVtZXJpYyhwb3J0XzUxNzQwX2xhbmRjb3Zlcl8yMDE4LnRpZiA9PSAxKSkNCg0Kd2F0ZXJfMTRfbWVhbiA8LSBjYWxjX2ZvY2FsX21lYW4ocG9ydF8xNF93YXRlciwgIndhdGVyIiwgMjUpDQp3YXRlcl8xOF9tZWFuIDwtIGNhbGNfZm9jYWxfbWVhbihwb3J0XzE4X3dhdGVyLCAid2F0ZXIiLCAyNSkNCg0KIyBPdGhlcg0KcG9ydF8xNF9vdGhlciA8LSBwb3J0XzE0XzEwX2Nyb3AgJT4lDQogIG11dGF0ZShvdGhlciA9IGFzLm51bWVyaWMocG9ydF81MTc0MF9sYW5kY292ZXJfMjAxNC50aWYgPT0gOCkpDQoNCnBvcnRfMThfb3RoZXIgPC0gcG9ydF8xOF8xMF9jcm9wICU+JQ0KICBtdXRhdGUob3RoZXIgPSBhcy5udW1lcmljKHBvcnRfNTE3NDBfbGFuZGNvdmVyXzIwMTgudGlmID09IDgpKQ0KDQpvdGhlcl8xNF9tZWFuIDwtIGZvY2FsMihwb3J0XzE0X290aGVyWyJvdGhlciJdLCBtYXRyaXgoMSwgMywgMyksICJtZWFuIikNCm90aGVyXzE0X21lYW4gPC0gZm9jYWwyKG90aGVyXzE0X21lYW5bIm90aGVyIl0sIG1hdHJpeCgxLCAzLCAzKSwgIm1lYW4iKQ0Kb3RoZXJfMThfbWVhbiA8LSBmb2NhbDIocG9ydF8xOF9vdGhlclsib3RoZXIiXSwgbWF0cml4KDEsIDMsIDMpLCAibWVhbiIpDQpvdGhlcl8xOF9tZWFuPC0gZm9jYWwyKG90aGVyXzE4X21lYW5bIm90aGVyIl0sIG1hdHJpeCgxLCAzLCAzKSwgIm1lYW4iKQ0KDQojIyBqb2luIGFsbCB0aGUgZGF0YQ0KDQpwb3J0MTQgPC0gY2JpbmQoDQogIGFzLmRhdGEuZnJhbWUoY2Fub3B5XzE0X21lYW4pWydjYW5vcHknXSwNCiAgYXMuZGF0YS5mcmFtZShyb2FkXzE0KVsncm9hZCddLA0KICBhcy5kYXRhLmZyYW1lKG90aGVyXzE0X21lYW4pWydvdGhlciddLA0KICBhcy5kYXRhLmZyYW1lKHNocnViXzE0X21lYW4pWydzaHJ1YiddLA0KICBhcy5kYXRhLmZyYW1lKHdhdGVyXzE0X21lYW4pWyd3YXRlciddLA0KICBhcy5kYXRhLmZyYW1lKHBvcnRfMTRfcGNudF9pbXBlcnYpWydsYyddICU+JQ0KICAgIHJlbmFtZShpbXBlcnYgPSBsYyApLA0KICBhcy5kYXRhLmZyYW1lKHBvcnRfY2hhbmdlX3JjKVs0XSU+JQ0KICAgIHJlbmFtZShsY2NoYW5nZSA9IGxjICkNCikNCg0KDQpwb3J0MTggPC0gY2JpbmQoDQogIGFzLmRhdGEuZnJhbWUoY2Fub3B5XzE4X21lYW4pWydjYW5vcHknXSwNCiAgYXMuZGF0YS5mcmFtZShyb2FkXzE4KVsncm9hZCddLA0KICBhcy5kYXRhLmZyYW1lKG90aGVyXzE4X21lYW4pWydvdGhlciddLA0KICBhcy5kYXRhLmZyYW1lKHNocnViXzE4X21lYW4pWydzaHJ1YiddLA0KICBhcy5kYXRhLmZyYW1lKHdhdGVyXzE4X21lYW4pWyd3YXRlciddLA0KICBhcy5kYXRhLmZyYW1lKHBvcnRfMThfcGNudF9pbXBlcnYpWydsYyddICU+JQ0KICAgIHJlbmFtZShpbXBlcnYgPSBsYyApDQopDQoNCg0KcG9ydF8xNCA8LSANCiAgc3Rfam9pbihwb3J0XzE0XzEwX3JjLHBvcnRfdHJhY3QpICU+JQ0KICBzdF9qb2luKC4sZGVtX3BvcnQpJT4lICMgbm90IGNoYW5naW5nDQogIHN0X2pvaW4oLixwb3J0X3Nsb3BlKSAlPiUNCiAgc3Rfam9pbiguLCBzb2lsX3BvcnQpDQoNCg0KcG9ydF8xOCA8LSANCiAgc3Rfam9pbihwb3J0XzE4XzEwX3JjLHBvcnRfdHJhY3QyKSAlPiUNCiAgc3Rfam9pbiguLGRlbV9wb3J0KSU+JSAjIG5vdCBjaGFuZ2luZw0KICBzdF9qb2luKC4scG9ydF9zbG9wZSkgJT4lDQogIHN0X2pvaW4oLiwgc29pbF9wb3J0KQ0KDQpybShkZW1fcG9ydCxwb3J0X3Nsb3BlLCBwb3J0XzE0XzEwX2Nyb3AsIHBvcnRfMTRfMTBfcmMsIHBvcnRfMTRfY2Fub3B5LCBwb3J0XzE0X290aGVyLCBwb3J0XzE0X3JvYWQsIHBvcnRfMTRfd2F0ZXIsIHBvcnRfMThfMTBfY3JvcCwgcG9ydF8xOF8xMF9yYywgcG9ydF8xOF9jYW5vcHksIHBvcnRfMThfb3RoZXIsIHBvcnRfMThfcm9hZCwgcG9ydF8xOF93YXRlcikNCg0KDQpwb3J0MTRfZGYgPC0gDQogIGFzLmRhdGEuZnJhbWUocG9ydF8xNCkgJT4lIA0KICByZW5hbWUoDQogICAgdGVycmFpbiA9IFVTR1NfMV9uMzd3MDc3XzIwMTYwMzE1LnRpZiApJT4lDQogIGNiaW5kKC4sIHBvcnQxNCklPiUgbmEub21pdCgpDQpwb3J0MThfZGYgPC0gDQogIGFzLmRhdGEuZnJhbWUocG9ydF8xOCkgJT4lIA0KICByZW5hbWUoDQogICAgdGVycmFpbiA9IFVTR1NfMV9uMzd3MDc3XzIwMTYwMzE1LnRpZikgJT4lDQogIGNiaW5kKC4sIHBvcnQxOCklPiVuYS5vbWl0KCkNCg0Kc2F2ZVJEUyhwb3J0MTRfZGYsICJ+L0dpdGh1Yi9QcmVjaXNpb24tRm9yZWNhc3RzLW9mLUxhbmQtQ292ZXItQ2hhbmdlL0RhdGEvb3V0cHV0L3BvcnQxNF9kZi5yZHMiKQ0Kc2F2ZVJEUyhwb3J0MThfZGYsICJ+L0dpdGh1Yi9QcmVjaXNpb24tRm9yZWNhc3RzLW9mLUxhbmQtQ292ZXItQ2hhbmdlL0RhdGEvb3V0cHV0L3BvcnQxOF9kZi5yZHMiKQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgIC0tLS0tLS0tLS0tLS0tLS0tLS0tICAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIHwgICAgICBKQU1FIENJVFkgICAgIHwgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyAgLS0tLS0tLS0tLS0tLS0tLS0tLS0gICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQojIFJvYWQNCmphbWVfMTRfcm9hZCA8LSBqYW1lXzE0XzEwX2Nyb3AgJT4lDQogIG11dGF0ZShyb2FkID0gYXMubnVtZXJpYyhqYW1lXzUxMDk1X2xhbmRjb3Zlcl8yMDE0LnRpZiA9PSA5KSkNCg0KamFtZV8xOF9yb2FkIDwtIGphbWVfMThfMTBfY3JvcCAlPiUNCiAgbXV0YXRlKHJvYWQgPSBhcy5udW1lcmljKGphbWVfNTEwOTVfbGFuZGNvdmVyXzIwMTgudGlmID09IDkpKQ0KDQpyb2FkXzE0IDwtIGNhbGNfZm9jYWxfbWVhbihqYW1lXzE0X3JvYWQsICJyb2FkIiwgMykNCnJvYWRfMTggPC0gY2FsY19mb2NhbF9tZWFuKGphbWVfMThfcm9hZCwgInJvYWQiLCAzKQ0KDQojIENhbm9weQ0KamFtZV8xNF9jYW5vcHkgPC0gamFtZV8xNF8xMF9jcm9wICU+JQ0KICBtdXRhdGUoY2Fub3B5ID0gYXMubnVtZXJpYyhqYW1lXzUxMDk1X2xhbmRjb3Zlcl8yMDE0LnRpZiA9PSAzKSkNCg0KamFtZV8xOF9jYW5vcHkgPC0gamFtZV8xOF8xMF9jcm9wICU+JQ0KICBtdXRhdGUoY2Fub3B5ID0gYXMubnVtZXJpYyhqYW1lXzUxMDk1X2xhbmRjb3Zlcl8yMDE4LnRpZiA9PSAzKSkNCg0KY2Fub3B5XzE0X21lYW4gPC0gY2FsY19mb2NhbF9tZWFuKGphbWVfMTRfY2Fub3B5LCAiY2Fub3B5IiwgMykNCmNhbm9weV8xOF9tZWFuIDwtIGNhbGNfZm9jYWxfbWVhbihqYW1lXzE4X2Nhbm9weSwgImNhbm9weSIsIDMpDQoNCiMgU2hydWINCmphbWVfMTRfc2hydWIgPC0gamFtZV8xNF8xMF9jcm9wICU+JQ0KICBtdXRhdGUoc2hydWIgPSBhcy5udW1lcmljKGphbWVfNTEwOTVfbGFuZGNvdmVyXzIwMTQudGlmID09IDIpKQ0KDQpqYW1lXzE4X3NocnViIDwtIGphbWVfMThfMTBfY3JvcCAlPiUNCiAgbXV0YXRlKHNocnViID0gYXMubnVtZXJpYyhqYW1lXzUxMDk1X2xhbmRjb3Zlcl8yMDE4LnRpZiA9PSAyKSkNCg0Kc2hydWJfMTRfbWVhbiA8LSBjYWxjX2ZvY2FsX21lYW4oamFtZV8xNF9zaHJ1YiwgInNocnViIiwgMykNCnNocnViXzE4X21lYW4gPC0gY2FsY19mb2NhbF9tZWFuKGphbWVfMThfc2hydWIsICJzaHJ1YiIsIDMpDQoNCiMgV2F0ZXINCmphbWVfMTRfd2F0ZXIgPC0gamFtZV8xNF8xMF9jcm9wICU+JQ0KICBtdXRhdGUod2F0ZXIgPSBhcy5udW1lcmljKGphbWVfNTEwOTVfbGFuZGNvdmVyXzIwMTQudGlmID09IDEpKQ0KDQpqYW1lXzE4X3dhdGVyIDwtIGphbWVfMThfMTBfY3JvcCAlPiUNCiAgbXV0YXRlKHdhdGVyID0gYXMubnVtZXJpYyhqYW1lXzUxMDk1X2xhbmRjb3Zlcl8yMDE4LnRpZiA9PSAxKSkNCg0Kd2F0ZXJfMTRfbWVhbiA8LSBjYWxjX2ZvY2FsX21lYW4oamFtZV8xNF93YXRlciwgIndhdGVyIiwgMjUpDQp3YXRlcl8xOF9tZWFuIDwtIGNhbGNfZm9jYWxfbWVhbihqYW1lXzE4X3dhdGVyLCAid2F0ZXIiLCAyNSkNCg0KIyBPdGhlcg0KamFtZV8xNF9vdGhlciA8LSBqYW1lXzE0XzEwX2Nyb3AgJT4lDQogIG11dGF0ZShvdGhlciA9IGFzLm51bWVyaWMoamFtZV81MTA5NV9sYW5kY292ZXJfMjAxNC50aWYgPT0gOCkpDQoNCmphbWVfMThfb3RoZXIgPC0gamFtZV8xOF8xMF9jcm9wICU+JQ0KICBtdXRhdGUob3RoZXIgPSBhcy5udW1lcmljKGphbWVfNTEwOTVfbGFuZGNvdmVyXzIwMTgudGlmID09IDgpKQ0KDQpvdGhlcl8xNF9tZWFuIDwtIGZvY2FsMihqYW1lXzE0X290aGVyWyJvdGhlciJdLCBtYXRyaXgoMSwgMywgMyksICJtZWFuIikNCm90aGVyXzE0X21lYW4gPC0gZm9jYWwyKG90aGVyXzE0X21lYW5bIm90aGVyIl0sIG1hdHJpeCgxLCAzLCAzKSwgIm1lYW4iKQ0Kb3RoZXJfMThfbWVhbiA8LSBmb2NhbDIoamFtZV8xOF9vdGhlclsib3RoZXIiXSwgbWF0cml4KDEsIDMsIDMpLCAibWVhbiIpDQpvdGhlcl8xOF9tZWFuPC0gZm9jYWwyKG90aGVyXzE4X21lYW5bIm90aGVyIl0sIG1hdHJpeCgxLCAzLCAzKSwgIm1lYW4iKQ0KDQojIyBqb2luIGFsbCB0aGUgZGF0YQ0KDQpqYW1lMTQgPC0gY2JpbmQoDQogIGFzLmRhdGEuZnJhbWUoY2Fub3B5XzE0X21lYW4pWydjYW5vcHknXSwNCiAgYXMuZGF0YS5mcmFtZShyb2FkXzE0KVsncm9hZCddLA0KICBhcy5kYXRhLmZyYW1lKG90aGVyXzE0X21lYW4pWydvdGhlciddLA0KICBhcy5kYXRhLmZyYW1lKHNocnViXzE0X21lYW4pWydzaHJ1YiddLA0KICBhcy5kYXRhLmZyYW1lKHdhdGVyXzE0X21lYW4pWyd3YXRlciddLA0KICBhcy5kYXRhLmZyYW1lKGphbWVfMTRfcGNudF9pbXBlcnYpWydsYyddICU+JQ0KICAgIHJlbmFtZShpbXBlcnYgPSBsYyApLA0KICBhcy5kYXRhLmZyYW1lKGphbWVfY2hhbmdlX3JjKVsnbGMnXSU+JQ0KICAgIHJlbmFtZShsY2NoYW5nZSA9IGxjICkNCikNCg0KamFtZTE4IDwtIGNiaW5kKA0KICBhcy5kYXRhLmZyYW1lKGNhbm9weV8xOF9tZWFuKVsnY2Fub3B5J10sDQogIGFzLmRhdGEuZnJhbWUocm9hZF8xOClbJ3JvYWQnXSwNCiAgYXMuZGF0YS5mcmFtZShvdGhlcl8xOF9tZWFuKVsnb3RoZXInXSwNCiAgYXMuZGF0YS5mcmFtZShzaHJ1Yl8xOF9tZWFuKVsnc2hydWInXSwNCiAgYXMuZGF0YS5mcmFtZSh3YXRlcl8xOF9tZWFuKVsnd2F0ZXInXSwNCiAgYXMuZGF0YS5mcmFtZShqYW1lXzE4X3BjbnRfaW1wZXJ2KVsnbGMnXSAlPiUNCiAgICByZW5hbWUoaW1wZXJ2ID0gbGMgKQ0KKQ0KamFtZV8xNCA8LSANCiAgc3Rfam9pbihqYW1lXzE0XzEwX3JjLGphbWVfdHJhY3QpICU+JQ0KICBzdF9qb2luKC4sZGVtX2phbWVzKSU+JSAjIG5vdCBjaGFuZ2luZw0KICBzdF9qb2luKC4samFtZXNfc2xvcGUpICU+JQ0KICBzdF9qb2luKC4sIHNvaWxfamFtZSkNCg0KDQpqYW1lXzE4IDwtIA0KICBzdF9qb2luKGphbWVfMThfMTBfcmMsamFtZV90cmFjdDIpICU+JQ0KICBzdF9qb2luKC4sZGVtX2phbWVzKSU+JSAjIG5vdCBjaGFuZ2luZw0KICBzdF9qb2luKC4samFtZXNfc2xvcGUpICU+JQ0KICBzdF9qb2luKC4sIHNvaWxfamFtZSkNCg0Kcm0oZGVtX2phbWUsamFtZV9zbG9wZSwgamFtZV8xNF8xMF9jcm9wLCBqYW1lXzE0XzEwX3JjLCBqYW1lXzE0X2Nhbm9weSwgamFtZV8xNF9vdGhlciwgamFtZV8xNF9yb2FkLCBqYW1lXzE0X3dhdGVyLCBqYW1lXzE4XzEwX2Nyb3AsIGphbWVfMThfMTBfcmMsIGphbWVfMThfY2Fub3B5LCBqYW1lXzE4X290aGVyLCBqYW1lXzE4X3JvYWQsIGphbWVfMThfd2F0ZXIpDQoNCmphbWUxNF9kZiA8LSANCiAgYXMuZGF0YS5mcmFtZShqYW1lXzE0KSAlPiUgDQogIHJlbmFtZSgNCiAgICB0ZXJyYWluID0gVVNHU18xX24zOHcwNzdfMjAxNzA1MDkudGlmICklPiUNCiAgY2JpbmQoLiwgamFtZTE0KSAgJT4lDQogIG5hLm9taXQoKSANCmphbWUxOF9kZiA8LSANCiAgYXMuZGF0YS5mcmFtZShqYW1lXzE4KSAlPiUgDQogIHJlbmFtZSgNCiAgICB0ZXJyYWluID0gVVNHU18xX24zOHcwNzdfMjAxNzA1MDkudGlmKSAlPiUNCiAgY2JpbmQoLiwgamFtZTE4KSU+JQ0KICBuYS5vbWl0KCkNCg0Kc2F2ZVJEUyhqYW1lMTRfZGYsICJ+L0dpdGh1Yi9QcmVjaXNpb24tRm9yZWNhc3RzLW9mLUxhbmQtQ292ZXItQ2hhbmdlL0RhdGEvb3V0cHV0L2phbWUxNF9kZi5yZHMiKQ0Kc2F2ZVJEUyhqYW1lMThfZGYsICJ+L0dpdGh1Yi9QcmVjaXNpb24tRm9yZWNhc3RzLW9mLUxhbmQtQ292ZXItQ2hhbmdlL0RhdGEvb3V0cHV0L2phbWUxOF9kZi5yZHMiKQ0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjICAtLS0tLS0tLS0tLS0tLS0tLS0tLSAgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyB8ICAgSVNMRSBvZiBXSUdIVCAgICB8ICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgIC0tLS0tLS0tLS0tLS0tLS0tLS0tICAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KIyBSb2FkDQppc2xlXzE0X3JvYWQgPC0gaXNsZV8xNF8xMF9jcm9wICU+JQ0KICBtdXRhdGUocm9hZCA9IGFzLm51bWVyaWMoaXNsZWxjXzE0XzEweDEwLnRpZiA9PSA5KSkNCg0KaXNsZV8xOF9yb2FkIDwtIGlzbGVfMThfMTBfY3JvcCAlPiUNCiAgbXV0YXRlKHJvYWQgPSBhcy5udW1lcmljKGlzbGVsY18xOF8xMHgxMC50aWYgPT0gOSkpDQoNCnJvYWRfMTQgPC0gY2FsY19mb2NhbF9tZWFuKGlzbGVfMTRfcm9hZCwgInJvYWQiLCAzKQ0Kcm9hZF8xOCA8LSBjYWxjX2ZvY2FsX21lYW4oaXNsZV8xOF9yb2FkLCAicm9hZCIsIDMpDQoNCiMgQ2Fub3B5DQppc2xlXzE0X2Nhbm9weSA8LSBpc2xlXzE0XzEwX2Nyb3AgJT4lDQogIG11dGF0ZShjYW5vcHkgPSBhcy5udW1lcmljKGlzbGVsY18xNF8xMHgxMC50aWYgPT0gMykpDQoNCmlzbGVfMThfY2Fub3B5IDwtIGlzbGVfMThfMTBfY3JvcCAlPiUNCiAgbXV0YXRlKGNhbm9weSA9IGFzLm51bWVyaWMoaXNsZWxjXzE4XzEweDEwLnRpZiA9PSAzKSkNCg0KY2Fub3B5XzE0X21lYW4gPC0gY2FsY19mb2NhbF9tZWFuKGlzbGVfMTRfY2Fub3B5LCAiY2Fub3B5IiwgMykNCmNhbm9weV8xOF9tZWFuIDwtIGNhbGNfZm9jYWxfbWVhbihpc2xlXzE4X2Nhbm9weSwgImNhbm9weSIsIDMpDQoNCiMgU2hydWINCmlzbGVfMTRfc2hydWIgPC0gaXNsZV8xNF8xMF9jcm9wICU+JQ0KICBtdXRhdGUoc2hydWIgPSBhcy5udW1lcmljKGlzbGVsY18xNF8xMHgxMC50aWYgPT0gMikpDQoNCmlzbGVfMThfc2hydWIgPC0gaXNsZV8xOF8xMF9jcm9wICU+JQ0KICBtdXRhdGUoc2hydWIgPSBhcy5udW1lcmljKGlzbGVsY18xOF8xMHgxMC50aWYgPT0gMikpDQoNCnNocnViXzE0X21lYW4gPC0gY2FsY19mb2NhbF9tZWFuKGlzbGVfMTRfc2hydWIsICJzaHJ1YiIsIDMpDQpzaHJ1Yl8xOF9tZWFuIDwtIGNhbGNfZm9jYWxfbWVhbihpc2xlXzE4X3NocnViLCAic2hydWIiLCAzKQ0KDQojIFdhdGVyDQppc2xlXzE0X3dhdGVyIDwtIGlzbGVfMTRfMTBfY3JvcCAlPiUNCiAgbXV0YXRlKHdhdGVyID0gYXMubnVtZXJpYyhpc2xlbGNfMTRfMTB4MTAudGlmID09IDEpKQ0KDQppc2xlXzE4X3dhdGVyIDwtIGlzbGVfMThfMTBfY3JvcCAlPiUNCiAgbXV0YXRlKHdhdGVyID0gYXMubnVtZXJpYyhpc2xlbGNfMThfMTB4MTAudGlmID09IDEpKQ0KDQp3YXRlcl8xNF9tZWFuIDwtIGNhbGNfZm9jYWxfbWVhbihpc2xlXzE0X3dhdGVyLCAid2F0ZXIiLCAyNSkNCndhdGVyXzE4X21lYW4gPC0gY2FsY19mb2NhbF9tZWFuKGlzbGVfMThfd2F0ZXIsICJ3YXRlciIsIDI1KQ0KDQojIE90aGVyDQppc2xlXzE0X290aGVyIDwtIGlzbGVfMTRfMTBfY3JvcCAlPiUNCiAgbXV0YXRlKG90aGVyID0gYXMubnVtZXJpYyhpc2xlbGNfMTRfMTB4MTAudGlmID09IDgpKQ0KDQppc2xlXzE4X290aGVyIDwtIGlzbGVfMThfMTBfY3JvcCAlPiUNCiAgbXV0YXRlKG90aGVyID0gYXMubnVtZXJpYyhpc2xlbGNfMThfMTB4MTAudGlmID09IDgpKQ0KDQpvdGhlcl8xNF9tZWFuIDwtIGZvY2FsMihpc2xlXzE0X290aGVyWyJvdGhlciJdLCBtYXRyaXgoMSwgMywgMyksICJtZWFuIikNCm90aGVyXzE0X21lYW4gPC0gZm9jYWwyKG90aGVyXzE0X21lYW5bIm90aGVyIl0sIG1hdHJpeCgxLCAzLCAzKSwgIm1lYW4iKQ0Kb3RoZXJfMThfbWVhbiA8LSBmb2NhbDIoaXNsZV8xOF9vdGhlclsib3RoZXIiXSwgbWF0cml4KDEsIDMsIDMpLCAibWVhbiIpDQpvdGhlcl8xOF9tZWFuPC0gZm9jYWwyKG90aGVyXzE4X21lYW5bIm90aGVyIl0sIG1hdHJpeCgxLCAzLCAzKSwgIm1lYW4iKQ0KDQojIyBqb2luIGFsbCB0aGUgZGF0YQ0KDQppc2xlMTQgPC0gY2JpbmQoDQogIGFzLmRhdGEuZnJhbWUoY2Fub3B5XzE0X21lYW4pWydjYW5vcHknXSwNCiAgYXMuZGF0YS5mcmFtZShyb2FkXzE0KVsncm9hZCddLA0KICBhcy5kYXRhLmZyYW1lKG90aGVyXzE0X21lYW4pWydvdGhlciddLA0KICBhcy5kYXRhLmZyYW1lKHNocnViXzE0X21lYW4pWydzaHJ1YiddLA0KICBhcy5kYXRhLmZyYW1lKHdhdGVyXzE0X21lYW4pWyd3YXRlciddLA0KICBhcy5kYXRhLmZyYW1lKGlzbGVfMTRfcGNudF9pbXBlcnYpWydsYyddICU+JQ0KICAgIHJlbmFtZShpbXBlcnYgPSBsYyApLA0KICBhcy5kYXRhLmZyYW1lKGlzbGVfY2hhbmdlX3JjKVtjKDUpXSU+JQ0KICAgIHJlbmFtZShsY2NoYW5nZSA9IGxjICkNCikNCg0KaXNsZTE4IDwtIGNiaW5kKA0KICBhcy5kYXRhLmZyYW1lKGNhbm9weV8xOF9tZWFuKVsnY2Fub3B5J10sDQogIGFzLmRhdGEuZnJhbWUocm9hZF8xOClbJ3JvYWQnXSwNCiAgYXMuZGF0YS5mcmFtZShvdGhlcl8xOF9tZWFuKVsnb3RoZXInXSwNCiAgYXMuZGF0YS5mcmFtZShzaHJ1Yl8xOF9tZWFuKVsnc2hydWInXSwNCiAgYXMuZGF0YS5mcmFtZSh3YXRlcl8xOF9tZWFuKVsnd2F0ZXInXSwNCiAgYXMuZGF0YS5mcmFtZShpc2xlXzE4X3BjbnRfaW1wZXJ2KVsnbGMnXSAlPiUNCiAgICByZW5hbWUoaW1wZXJ2ID0gbGMgKQ0KKQ0KDQppc2xlMTQgPC0gIGNiaW5kKGlzbGVfMTRfMTBfY3JvcCxjYW5vcHlfMTRfbWVhbiwgcm9hZF8xNCwgb3RoZXJfMTRfbWVhbiwgc2hydWJfMTRfbWVhbiwgd2F0ZXJfMTRfbWVhbiwgaXNsZV8xNF9wY250X2ltcGVydiwgaXNsZV9jaGFuZ2VfcmMsaXNsZV9jaGFuZ2UpICMgY2hhbmdlIGltcGVydmlvdXMoMCwgMSwgLTEpIDEgaXMgdGFyZ2V0ZWQNCnJtKGNhbm9weV8xNF9tZWFuLCByb2FkXzE0LCBvdGhlcl8xNF9tZWFuLCBzaHJ1Yl8xNF9tZWFuLCB3YXRlcl8xNF9tZWFuLCBpc2xlXzE0X3BjbnRfaW1wZXJ2LCBpc2xlX2NoYW5nZV9yYykNCg0KaXNsZTE4IDwtIGNiaW5kKGlzbGVfMThfMTBfY3JvcCwgY2Fub3B5XzE4X21lYW4sIHJvYWRfMTgsb3RoZXJfMThfbWVhbiwgc2hydWJfMThfbWVhbiwgd2F0ZXJfMThfbWVhbixpc2xlXzE4X3BjbnRfaW1wZXJ2KQ0Kcm0oY2Fub3B5XzE4X21lYW4sIHJvYWRfMTgsIG90aGVyXzE4X21lYW4sIHNocnViXzE4X21lYW4sIHdhdGVyXzE4X21lYW4sIGlzbGVfMThfcGNudF9pbXBlcnYpDQoNCmlzbGVfMTQgPC0gDQogIHN0X2pvaW4oaXNsZV8xNF8xMF9yYyxpc2xlX3RyYWN0KSAlPiUNCiAgc3Rfam9pbiguLGRlbV9pc2xlKSU+JSAjIG5vdCBjaGFuZ2luZw0KICBzdF9qb2luKC4saXNsZV9zbG9wZSkgJT4lDQogIHN0X2pvaW4oLiwgc29pbF9pc2xlKQ0KDQoNCmlzbGVfMTggPC0gDQogIHN0X2pvaW4oaXNsZV8xOF8xMF9yYyxpc2xlX3RyYWN0MikgJT4lDQogIHN0X2pvaW4oLixkZW1faXNsZSklPiUgIyBub3QgY2hhbmdpbmcNCiAgc3Rfam9pbiguLGlzbGVfc2xvcGUpICU+JQ0KICBzdF9qb2luKC4sIHNvaWxfaXNsZSkNCg0Kcm0oZGVtX2lzbGUsaXNsZV9zbG9wZSwgaXNsZV8xNF8xMF9jcm9wLCBpc2xlXzE0XzEwX3JjLCBpc2xlXzE0X2Nhbm9weSwgaXNsZV8xNF9vdGhlciwgaXNsZV8xNF9yb2FkLCBpc2xlXzE0X3NocnViLCBpc2xlXzE4XzEwX2Nyb3AsIGlzbGVfMThfMTBfcmMsIGlzbGVfMThfY2Fub3B5LCBpc2xlXzE4X290aGVyLCBpc2xlXzE4X3JvYWQsIGlzbGVfMThfc2hydWIpDQoNCmlzbGUxNF9kZiA8LSANCiAgYXMuZGF0YS5mcmFtZShpc2xlXzE0KSAgJT4lDQogIHJlbmFtZSh0ZXJyYWluID0gVVNHU18xX24zOHcwNzdfMjAxNzA1MDkudGlmICklPiUNCiAgY2JpbmQoLiwgaXNsZTE0KSAlPiUgDQogIG5hLm9taXQoKQ0KaXNsZTE4X2RmIDwtIA0KICBhcy5kYXRhLmZyYW1lKGlzbGVfMTgpICU+JSANCiAgcmVuYW1lKHRlcnJhaW4gPSBVU0dTXzFfbjM4dzA3N18yMDE3MDUwOS50aWYpICU+JQ0KICBjYmluZCguLCBpc2xlMTgpJT4lDQogIG5hLm9taXQoKQ0KDQpzYXZlUkRTKGlzbGUxNF9kZiwgIn4vR2l0aHViL1ByZWNpc2lvbi1Gb3JlY2FzdHMtb2YtTGFuZC1Db3Zlci1DaGFuZ2UvRGF0YS9vdXRwdXQvaXNsZTE0X2RmLnJkcyIpDQpzYXZlUkRTKGlzbGUxOF9kZiwgIn4vR2l0aHViL1ByZWNpc2lvbi1Gb3JlY2FzdHMtb2YtTGFuZC1Db3Zlci1DaGFuZ2UvRGF0YS9vdXRwdXQvaXNsZTE4X2RmLnJkcyIpDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgIC0tLS0tLS0tLS0tLS0tLS0tLS0tICAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIHwgICAgICAgICAgICAgICAgICAgIHwgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyB8ICAgICAgTU9ERUxJTkcgICAgICB8ICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgfCAgICAgICAgICAgICAgICAgICAgfCAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjICAtLS0tLS0tLS0tLS0tLS0tLS0tLSAgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCg0KDQpzZXQuc2VlZCg3MTcpDQoNCg0KIiUhaW4lIiA8LSBOZWdhdGUoIiVpbiUiKQ0KDQppc2xlMTRfZGYgPC0gcmVhZFJEUyggIn4vR2l0aHViL1ByZWNpc2lvbi1Gb3JlY2FzdHMtb2YtTGFuZC1Db3Zlci1DaGFuZ2UvRGF0YS9vdXRwdXQvaXNsZTE0X2RmLnJkcyIpDQpqYW1lMTRfZGYgPC0gcmVhZFJEUyggIn4vR2l0aHViL1ByZWNpc2lvbi1Gb3JlY2FzdHMtb2YtTGFuZC1Db3Zlci1DaGFuZ2UvRGF0YS9vdXRwdXQvamFtZTE0X2RmLnJkcyIpDQpwb3J0MTRfZGYgPC0gcmVhZFJEUyggIn4vR2l0aHViL1ByZWNpc2lvbi1Gb3JlY2FzdHMtb2YtTGFuZC1Db3Zlci1DaGFuZ2UvRGF0YS9vdXRwdXQvcG9ydDE0X2RmLnJkcyIpDQoNCg0KDQojIERhdGEgcHJlcGFyYXRpb24NCmRhdGEgPC0gZGF0YSAlPiUgDQogIG11dGF0ZSgNCiAgICBsY3JlID0gY2FzZV93aGVuKGxjY2hhbmdlID09IC0xIH4gMCwNCiAgICAgICAgICAgICAgICAgICAgIGxjY2hhbmdlID09IDEgfiAxLA0KICAgICAgICAgICAgICAgICAgICAgbGNjaGFuZ2UgPT0gMCB+IDApDQogICkgJT4lIA0KICBtdXRhdGUoDQogICAgbGNjaGFuZ2UgPSBhcy5mYWN0b3IobGNjaGFuZ2UpLA0KICAgIGxjcmUgPSBhcy5mYWN0b3IobGNyZSkNCiAgKQ0KDQoNCiMgSW5pdGlhbCBzcGxpdCBmb3IgdHJhaW5pbmcgYW5kIHRlc3QNCmRhdGFfc3BsaXQgPC0gaW5pdGlhbF9zcGxpdChkYXRhLCBzdHJhdGEgPSAibGNjaGFuZ2UiLCBwcm9wID0gMC44KQ0KZGF0YV90cmFpbiA8LSB0cmFpbmluZyhkYXRhX3NwbGl0KQ0KZGF0YV90ZXN0IDwtIHRlc3RpbmcoZGF0YV9zcGxpdCkNCg0KYXBwbHlfbW9kZWxfcmYgPC0gZnVuY3Rpb24oZGF0YSkgew0KICAjIFNhbXBsZSBkYXRhDQogIGJhbGFuY2VkX2RhdGEgPC0gZGF0YV90cmFpbltjKHNhbXBsZSh3aGljaChkYXRhX3RyYWluJGxjcmUgPT0gMCksIHN1bShkYXRhX3RyYWluJGxjcmUgPT0gMSkgKjEwKSAsIHdoaWNoKGRhdGFfdHJhaW4kbGNyZSA9PSAxKSksXQ0KICAjIENyb3NzLXZhbGlkYXRpb24NCiAgY3Zfc3BsaXRzX2dlbyA8LSBncm91cF92Zm9sZF9jdihiYWxhbmNlZF9kYXRhLCBncm91cCA9ICJHRU9JRCIpDQogIA0KICAjIENyZWF0ZSByZWNpcGUNCiAgbW9kZWxfcmVjIDwtIHJlY2lwZShsY3JlIH4gLiwgZGF0YSA9IGJhbGFuY2VkX2RhdGEpICU+JQ0KICAgIHVwZGF0ZV9yb2xlKEdFT0lELCBuZXdfcm9sZSA9ICJHRU9JRCIpICU+JSAjNzgNCiAgICB1cGRhdGVfcm9sZShsY2NoYW5nZSwgbmV3X3JvbGUgPSAibGNjaGFuZ2UiKSAlPiUNCiAgICB1cGRhdGVfcm9sZShwb3J0XzUxNzQwX2xhbmRjb3Zlcl8yMDE0LnRpZiwgbmV3X3JvbGUgPSAib3JpZ2luYWxsYyIpICU+JQ0KICAgIHVwZGF0ZV9yb2xlKGxjLCBuZXdfcm9sZSA9ICJsYyIpIyAlPiUNCiAgc3RlcF9ucyh4LCB5LCBvcHRpb25zID0gbGlzdChkZiA9IDEpKQ0KICANCiAgIyBNb2RlbCBzcGVjaWZpY2F0aW9ucw0KICByZl9wbGFuIDwtIHJhbmRfZm9yZXN0KCkgJT4lDQogICAgc2V0X2FyZ3MobXRyeSAgPSB0dW5lKCkpICU+JQ0KICAgIHNldF9hcmdzKG1pbl9uID0gdHVuZSgpKSAlPiUgICMgMTAwLDEwMDAsc2VxPTIwMA0KICAgIHNldF9hcmdzKHRyZWVzID0gIHR1bmUoKSkgJT4lICMgMTAwMA0KICAgICNzZXRfYXJncyhtYXhfZGVwdGggID0gIDEwKSAlPiUgDQogICAgc2V0X2VuZ2luZSgicmFuZ2VyIiwgaW1wb3J0YW5jZSA9ICJpbXB1cml0eSIpICU+JSANCiAgICBzZXRfbW9kZSgiY2xhc3NpZmljYXRpb24iKQ0KICANCiAgcmZfZ3JpZCA8LSBleHBhbmQuZ3JpZChtdHJ5ID0gYyg1LDEwLDE1KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICBtaW5fbiAgPSBjKDEwMCw1MDAsOTAwKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICB0cmVlcyA9ICBjKDEwMDAsMTUwMCkNCiAgKQ0KICANCiAgIyBDcmVhdGUgdGhlIHdvcmtmbG93DQogIHJmX3dmIDwtDQogICAgd29ya2Zsb3coKSAlPiUgDQogICAgYWRkX3JlY2lwZShtb2RlbF9yZWMpICU+JSANCiAgICBhZGRfbW9kZWwocmZfcGxhbikNCiAgDQogICMgVHVuZSBoeXBlcnBhcmFtZXRlcnMNCiAgY29udHJvbCA8LSBjb250cm9sX3Jlc2FtcGxlcyhzYXZlX3ByZWQgPSBUUlVFLCB2ZXJib3NlID0gVFJVRSkNCiAgbWV0cmljcyA8LSBtZXRyaWNfc2V0KGZfbWVhcykNCiAgDQogIHJmX3R1bmVkIDwtIHJmX3dmICU+JQ0KICAgIHR1bmVfZ3JpZChyZXNhbXBsZXMgPSBjdl9zcGxpdHNfZ2VvLA0KICAgICAgICAgICAgICBncmlkICAgICAgPSByZl9ncmlkLA0KICAgICAgICAgICAgICBjb250cm9sICAgPSBjb250cm9sLA0KICAgICAgICAgICAgICBtZXRyaWNzICAgPSBtZXRyaWNzKQ0KICANCiAgIyBTZWxlY3QgYmVzdCBtb2RlbA0KICByZl9iZXN0X3BhcmFtcyA8LSBzZWxlY3RfYmVzdChyZl90dW5lZCwgbWV0cmljID0gImZfbWVhcyIpDQogIHJmX2Jlc3Rfd2YgPC0gZmluYWxpemVfd29ya2Zsb3cocmZfd2YsIHJmX2Jlc3RfcGFyYW1zKQ0KICANCiAgcmV0dXJuKHJmX2Jlc3Rfd2YpDQp9DQoNCiMgRml0IG11bHRpcGxlIG1vZGVscw0KbnVtX21vZGVscyA8LSA1DQpwcmVkaWN0X2RmcyA8LSBsaXN0KCkNCnJmX3dmcyA8LSBsaXN0KCkNCmZvciAoaSBpbiAxOm51bV9tb2RlbHMpIHsNCiAgIyBTcGxpdCBkYXRhDQogIHJmX3dmIDwtIGFwcGx5X21vZGVsX3JmKGRhdGFfdHJhaW4pDQogIA0KICAjIE1ha2UgcHJlZGljdGlvbnMNCiAgcmZfZnVsbF93ZiA8LSByZl93ZiAlPiUNCiAgICBmaXQoZGF0YSkNCiAgcHJlZGljdF9kZiA8LQ0KICAgIHByZWRpY3QocmZfZnVsbF93ZiAsIG5ld19kYXRhID0gZGF0YSwgdHlwZSA9ICJwcm9iIikNCiAgIyBBZGQgdG8gbGlzdA0KICBwcmVkaWN0X2Rmc1tbaV1dIDwtIHByZWRpY3RfZGZbMl0NCiAgcmZfd2ZzW1tpXV0gPC0gcmZfZnVsbF93Zg0KfQ0KDQoNCiMgQXBwbHkgbW9kZWwgdG8gdGhyZWUgZGlmZmVyZW50IGRhdGFzZXRzDQpyZXN1bHRzX2lzbGU8LSBhcHBseV9tb2RlbChpc2xlMTRfZGYpDQpyZXN1bHRzX3BvcnQ8LSBhcHBseV9tb2RlbChwb3J0MTRfZGYpDQpyZXN1bHRzX2phbWUgPC0gYXBwbHlfbW9kZWwoamFtZTE0X2RmKQ0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjICAtLS0tLS0tLS0tLS0tLS0tLS0tLSAgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyB8ICAgICAgICAgICAgICAgICAgICB8ICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgfCAgICAgUFJFRElDVElORyAgICAgfCAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIHwgICAgICAgICAgICAgICAgICAgIHwgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyAgLS0tLS0tLS0tLS0tLS0tLS0tLS0gICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQppc2xlMThfZGYgPC0gcmVhZFJEUygifi9HaXRodWIvUHJlY2lzaW9uLUZvcmVjYXN0cy1vZi1MYW5kLUNvdmVyLUNoYW5nZS9EYXRhL291dHB1dC9pc2xlMThfZGYucmRzIikNCnBvcnQxOF9kZiA8LSByZWFkUkRTKCJ+L0dpdGh1Yi9QcmVjaXNpb24tRm9yZWNhc3RzLW9mLUxhbmQtQ292ZXItQ2hhbmdlL0RhdGEvb3V0cHV0L3BvcnQxOF9kZi5yZHMiKQ0KamFtZTE4X2RmIDwtIHJlYWRSRFMoIn4vR2l0aHViL1ByZWNpc2lvbi1Gb3JlY2FzdHMtb2YtTGFuZC1Db3Zlci1DaGFuZ2UvRGF0YS9vdXRwdXQvamFtZTE4X2RmLnJkcyIpDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgIC0tLS0tLS0tLS0tLS0tLS0tLS0tICAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIHwgICAgICBKQU1FIENJVFkgICAgIHwgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyAgLS0tLS0tLS0tLS0tLS0tLS0tLS0gICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyBGaXQgdGhlIGJlc3QgbW9kZWwgdG8gdGhlIHdob2xlIGRhdGFzZXQNCmZ1bGxfZml0X3JmIDwtIHJlc3VsdHNfamFtZVsxXVsyXSU+JQ0KICBmaXQoZGF0YSA9IGphbWUxNF9kZikNCg0KIyBTZWUgdGhlIHByZWRpY3Rpb24gZm9yIHRoZSBmdWxsIGRhdGFzZXQNCnByZWRpY3RfZGYgPC0gcHJlZGljdChmdWxsX2ZpdF9yZiwgbmV3X2RhdGEgPSBqYW1lMTRfZGYpDQpwcmVkaWN0X2RmMiA8LSBjYmluZChqYW1lMTRfZGYscHJlZGljdF9kZikgJT4lDQogIG11dGF0ZShlcnJvciA9IGFzLm51bWVyaWMoLnByZWRfY2xhc3MpIC0gYXMubnVtZXJpYyhsY3JlKSkNCg0KIyBVc2UgdGhlIGJlc3QgbW9kZWwgdG8gcHJlZGljdCBmb3IgdGhlIGZ1dHVyZQ0KcHJlZGljdF9kZjMgPC0gcHJlZGljdChmdWxsX2ZpdF9yZiwgbmV3X2RhdGEgPSBqYW1lMThfZGYgJT4lIG11dGF0ZShsY2NoYW5nZSA9IGFzLmZhY3RvcihsYykpKQ0KcHJlZGljdF9kZjMgPC0gY2JpbmQoamFtZTE4X2RmLHByZWRpY3RfZGYzKSANCnNhdmVSRFMocHJlZGljdF9kZjMsJ34vR2l0aHViL1ByZWNpc2lvbi1Gb3JlY2FzdHMtb2YtTGFuZC1Db3Zlci1DaGFuZ2UvRGF0YS9vdXRwdXQvcHJlZGljdF9ERjNfamFtZS5yZHMnKQ0KDQojIGV4dHJhY3QgZmluYWwgbW9kZWwgb2JqZWN0DQpyZl9mdWxsX21vZCA8LSBleHRyYWN0X2ZpdF9wYXJzbmlwKGZ1bGxfZml0X3JmKQ0Kc2F2ZVJEUyhyZl9mdWxsX21vZCwnfi9HaXRodWIvUHJlY2lzaW9uLUZvcmVjYXN0cy1vZi1MYW5kLUNvdmVyLUNoYW5nZS9EYXRhL291dHB1dC9iZXN0X3JmMV9qYW1lLnJkcycpDQoNCmltcCA8LSBpbXBvcnRhbmNlKHJmX2Z1bGxfbW9kJGZpdCwgdHlwZSA9IDEpDQppZiAoaXMubWF0cml4KGltcCkpIHsNCiAgaW1wX2RmIDwtIGRhdGEuZnJhbWUodmFyaWFibGUgPSByb3duYW1lcyhpbXApLCBpbXBvcnRhbmNlID0gaW1wWywgMV0pDQp9IGVsc2Ugew0KICBpbXBfZGYgPC0gZGF0YS5mcmFtZSh2YXJpYWJsZSA9IG5hbWVzKGltcCksIGltcG9ydGFuY2UgPSBpbXApDQp9DQoNCg0KZ2dwbG90KGltcF9kZiwgYWVzKHggPSByZW9yZGVyKHZhcmlhYmxlLCBpbXBvcnRhbmNlKSwgeSA9IGltcG9ydGFuY2UsIGZpbGwgPSAiIzQxYjZjNCIsIGFscGhhPTAuNSkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsNCiAgY29vcmRfZmxpcCgpICsNCiAgc2NhbGVfZmlsbF9pZGVudGl0eSgpICsNCiAgbGFicyh4ID0gIlZhcmlhYmxlIiwgeSA9ICJJbXBvcnRhbmNlIikgKw0KICBnZ3RpdGxlKCJWYXJpYWJsZSBJbXBvcnRhbmNlIikNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgIC0tLS0tLS0tLS0tLS0tLS0tLS0tICAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIHwgICAgICBQT1JUTU9VVEggICAgIHwgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyAgLS0tLS0tLS0tLS0tLS0tLS0tLS0gICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQojIEZpdCB0aGUgYmVzdCBtb2RlbCB0byB0aGUgd2hvbGUgZGF0YXNldA0KZnVsbF9maXRfcmYgPC0gcmVzdWx0c19wb3J0WzFdWzJdJT4lDQogIGZpdChkYXRhID0gcG9ydDE0X2RmKQ0KDQojIFNlZSB0aGUgcHJlZGljdGlvbiBmb3IgdGhlIGZ1bGwgZGF0YXNldA0KcHJlZGljdF9kZiA8LSBwcmVkaWN0KGZ1bGxfZml0X3JmLCBuZXdfZGF0YSA9IHBvcnQxNF9kZikNCnByZWRpY3RfZGYyIDwtIGNiaW5kKHBvcnQxNF9kZixwcmVkaWN0X2RmKSAlPiUNCiAgbXV0YXRlKGVycm9yID0gYXMubnVtZXJpYygucHJlZF9jbGFzcykgLSBhcy5udW1lcmljKGxjcmUpKQ0KDQojIFVzZSB0aGUgYmVzdCBtb2RlbCB0byBwcmVkaWN0IGZvciB0aGUgZnV0dXJlDQpwcmVkaWN0X2RmMyA8LSBwcmVkaWN0KGZ1bGxfZml0X3JmLCBuZXdfZGF0YSA9IHBvcnQxOF9kZiAlPiUgbXV0YXRlKGxjY2hhbmdlID0gYXMuZmFjdG9yKGxjKSkpDQpwcmVkaWN0X2RmMyA8LSBjYmluZChwb3J0MThfZGYscHJlZGljdF9kZjMpIA0Kc2F2ZVJEUyhwcmVkaWN0X2RmMywnfi9HaXRodWIvUHJlY2lzaW9uLUZvcmVjYXN0cy1vZi1MYW5kLUNvdmVyLUNoYW5nZS9EYXRhL291dHB1dC9wcmVkaWN0X0RGM19wb3J0LnJkcycpDQoNCiMgZXh0cmFjdCBmaW5hbCBtb2RlbCBvYmplY3QNCnJmX2Z1bGxfbW9kIDwtIGV4dHJhY3RfZml0X3BhcnNuaXAoZnVsbF9maXRfcmYpDQpzYXZlUkRTKHJmX2Z1bGxfbW9kLCd+L0dpdGh1Yi9QcmVjaXNpb24tRm9yZWNhc3RzLW9mLUxhbmQtQ292ZXItQ2hhbmdlL0RhdGEvb3V0cHV0L2Jlc3RfcmYxX3BvcnQucmRzJykNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyAgLS0tLS0tLS0tLS0tLS0tLS0tLS0gICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgfCAgIElTTEUgT0YgV0lHSFQgICAgfCAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjICAtLS0tLS0tLS0tLS0tLS0tLS0tLSAgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIEZpdCB0aGUgYmVzdCBtb2RlbCB0byB0aGUgd2hvbGUgZGF0YXNldA0KZnVsbF9maXRfcmYgPC0gcmVzdWx0c19qYW1lWzFdWzJdJT4lDQogIGZpdChkYXRhID0gcG9ydDE0X2RmKQ0KDQojIFNlZSB0aGUgcHJlZGljdGlvbiBmb3IgdGhlIGZ1bGwgZGF0YXNldA0KcHJlZGljdF9kZiA8LSBwcmVkaWN0KGZ1bGxfZml0X3JmLCBuZXdfZGF0YSA9IGlzbGUxNF9kZikNCnByZWRpY3RfZGYyIDwtIGNiaW5kKGlzbGUxNF9kZixwcmVkaWN0X2RmKSAlPiUNCiAgbXV0YXRlKGVycm9yID0gYXMubnVtZXJpYygucHJlZF9jbGFzcykgLSBhcy5udW1lcmljKGxjcmUpKQ0KDQojIFVzZSB0aGUgYmVzdCBtb2RlbCB0byBwcmVkaWN0IGZvciB0aGUgZnV0dXJlDQpwcmVkaWN0X2RmMyA8LSBwcmVkaWN0KGZ1bGxfZml0X3JmLCBuZXdfZGF0YSA9IGlzbGUxOF9kZiAlPiUgbXV0YXRlKGxjY2hhbmdlID0gYXMuZmFjdG9yKGxjKSkpDQpwcmVkaWN0X2RmMyA8LSBjYmluZChpc2xlMThfZGYscHJlZGljdF9kZjMpIA0Kc2F2ZVJEUyhwcmVkaWN0X2RmMywnfi9HaXRodWIvUHJlY2lzaW9uLUZvcmVjYXN0cy1vZi1MYW5kLUNvdmVyLUNoYW5nZS9EYXRhL291dHB1dC9wcmVkaWN0X0RGM19pc2xlLnJkcycpDQoNCiMgZXh0cmFjdCBmaW5hbCBtb2RlbCBvYmplY3QNCnJmX2Z1bGxfbW9kIDwtIGV4dHJhY3RfZml0X3BhcnNuaXAoZnVsbF9maXRfcmYpDQpzYXZlUkRTKHJmX2Z1bGxfbW9kLCd+L0dpdGh1Yi9QcmVjaXNpb24tRm9yZWNhc3RzLW9mLUxhbmQtQ292ZXItQ2hhbmdlL0RhdGEvb3V0cHV0L2Jlc3RfcmYxX2lzbGUucmRzJykNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyAgLS0tLS0tLS0tLS0tLS0tLS0tLS0gICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgfCAgICAgICAgICAgICAgICAgICAgfCAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIHwgICAgICBNQVBQSU5HICAgICAgIHwgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyB8ICAgICAgICAgICAgICAgICAgICB8ICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgIC0tLS0tLS0tLS0tLS0tLS0tLS0tICAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KDQpwcmVkaWN0X2RmMjwtIHJlYWRSRFMoJ34vR2l0aHViL1ByZWNpc2lvbi1Gb3JlY2FzdHMtb2YtTGFuZC1Db3Zlci1DaGFuZ2UvRGF0YS9vdXRwdXQvcHJlZGljdF9ERjNfcG9ydC5yZHMnKQ0KcyA8LSBzdF9hc19zdGFycyhwcmVkaWN0X2RmMiwNCiAgICAgICAgICAgICAgICAgZGltZW5zaW9ucz1zdF9kaW1lbnNpb25zKA0KICAgICAgICAgICAgICAgICAgIHg9c29ydCh1bmlxdWUoZGYkeCkpLA0KICAgICAgICAgICAgICAgICAgIHk9c29ydCh1bmlxdWUoZGYkeSkpLCANCiAgICAgICAgICAgICAgICAgICBwb2ludD1UUlVFKSwNCiAgICAgICAgICAgICAgICAgZGltcz1jKCd4JywneScpKQ0Kc3RfY3JzKHMpIDwtIHN0X2Nycyhwb3J0XzE0KQ0KcyA8LSBzJT4lDQogIHN0X3RyYW5zZm9ybSg0MzI2KQ0KeCA8LSBzWycucHJlZF9jbGFzcyddDQp4Lm9yIDwtc1snbGNyZSddDQplcnJvciA8LSBzWydlcnJvciddDQp0aHJlc2hfdmFsdWUgPC0gMQ0KeFt4ICE9IHRocmVzaF92YWx1ZV0gPC0gTkENCnhfc2YgPC0gc3RfdW5pb24oc3RfYXNfc2YoeCkpDQojIHdyaXRlIHRoZSBzZiBvYmplY3QgdG8gYSBHZW9KU09OIGZpbGUNCmdlb2pzb25fcGF0aCA8LSAifi9HaXRodWIvUHJlY2lzaW9uLUZvcmVjYXN0cy1vZi1MYW5kLUNvdmVyLUNoYW5nZS9EYXRhL291dHB1dC9wb3J0X3ByZWRpY3RfeGdiLmdlb2pzb24iDQpzdF93cml0ZSh4X3NmLCBnZW9qc29uX3BhdGgpDQoNCg0KDQpwcmVkaWN0X2RmMjwtIHJlYWRSRFMoJ34vR2l0aHViL1ByZWNpc2lvbi1Gb3JlY2FzdHMtb2YtTGFuZC1Db3Zlci1DaGFuZ2UvRGF0YS9vdXRwdXQvcHJlZGljdF9ERjNfcG9ydC5yZHMnKQ0KcyA8LSBzdF9hc19zdGFycyhwcmVkaWN0X2RmMiwNCiAgICAgICAgICAgICAgICAgZGltZW5zaW9ucz1zdF9kaW1lbnNpb25zKA0KICAgICAgICAgICAgICAgICAgIHg9c29ydCh1bmlxdWUoZGYkeCkpLA0KICAgICAgICAgICAgICAgICAgIHk9c29ydCh1bmlxdWUoZGYkeSkpLCANCiAgICAgICAgICAgICAgICAgICBwb2ludD1UUlVFKSwNCiAgICAgICAgICAgICAgICAgZGltcz1jKCd4JywneScpKQ0Kc3RfY3JzKHMpIDwtIHN0X2Nycyhwb3J0XzE4KQ0KcyA8LSBzJT4lDQogIHN0X3RyYW5zZm9ybSg0MzI2KQ0KeCA8LSBzWycucHJlZF9jbGFzcyddDQp4Lm9yIDwtc1snbGNyZSddDQplcnJvciA8LSBzWydlcnJvciddDQp0aHJlc2hfdmFsdWUgPC0gMQ0KeFt4ICE9IHRocmVzaF92YWx1ZV0gPC0gTkENCnhfc2YgPC0gc3RfdW5pb24oc3RfYXNfc2YoeCkpDQojIHdyaXRlIHRoZSBzZiBvYmplY3QgdG8gYSBHZW9KU09OIGZpbGUNCmdlb2pzb25fcGF0aCA8LSAifi9HaXRodWIvUHJlY2lzaW9uLUZvcmVjYXN0cy1vZi1MYW5kLUNvdmVyLUNoYW5nZS9EYXRhL291dHB1dC9wb3J0X3Rlc3RfNDMyNi5nZW9qc29uIg0Kc3Rfd3JpdGUoeF9zZiwgZ2VvanNvbl9wYXRoKQ0KYGBgDQo=
3.3 Social and Economical Factors
Social and economic factors, which change over time, also impact land cover changes. We investigated variables such as population growth, economic development, and demographic changes to understand how these factors contributed to land cover conversion. By incorporating these dynamic factors into our analysis, we were able to better forecast land cover changes based on potential future scenarios.
The plots presented here illustrate that the percentage of white population change exhibits a different pattern in areas of land cover change compared to the overall county. This observation indicates that in Portsmouth County, land cover change is also associated with changes in census data, particularly the percentage of white population change.